summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorratchov <ratchov@openbsd.org>2010-05-02 11:12:31 +0000
committerratchov <ratchov@openbsd.org>2010-05-02 11:12:31 +0000
commit9c3361900161e96fa045beffb5c0daa150a71b8c (patch)
tree733571c83f960b9c45b132ab2a8a3cf8bc0860f2
parentuse clock_gettime() and interval timers instead of gettimeofday() (diff)
downloadwireguard-openbsd-9c3361900161e96fa045beffb5c0daa150a71b8c.tar.xz
wireguard-openbsd-9c3361900161e96fa045beffb5c0daa150a71b8c.zip
Don't systematically fill with silence the mixer output. This
might result in extra samples being written to the device when the mixer is closed.
-rw-r--r--usr.bin/aucat/aproc.c81
-rw-r--r--usr.bin/aucat/aproc.h7
-rw-r--r--usr.bin/aucat/aucat.c34
-rw-r--r--usr.bin/aucat/dev.c39
4 files changed, 114 insertions, 47 deletions
diff --git a/usr.bin/aucat/aproc.c b/usr.bin/aucat/aproc.c
index c626ab7aaf0..d5ab22176f4 100644
--- a/usr.bin/aucat/aproc.c
+++ b/usr.bin/aucat/aproc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: aproc.c,v 1.56 2010/05/02 10:40:48 ratchov Exp $ */
+/* $OpenBSD: aproc.c,v 1.57 2010/05/02 11:12:31 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -577,16 +577,21 @@ mix_drop(struct abuf *buf, int extra)
}
/*
- * Append the given amount of silence (or less if there's not enough
- * space), and crank w.mix.todo accordingly.
+ * Append the necessary amount of silence, in a way
+ * obuf->w.mix.todo doesn't exceed the given value
*/
void
-mix_bzero(struct abuf *obuf)
+mix_bzero(struct abuf *obuf, unsigned maxtodo)
{
short *odata;
- unsigned ocount;
+ unsigned ocount, todo;
+ if (obuf->w.mix.todo >= maxtodo)
+ return;
+ todo = maxtodo - obuf->w.mix.todo;
odata = (short *)abuf_wgetblk(obuf, &ocount, obuf->w.mix.todo);
+ if (ocount > todo)
+ ocount = todo;
if (ocount == 0)
return;
memset(odata, 0, ocount * obuf->bpf);
@@ -628,11 +633,12 @@ mix_badd(struct abuf *ibuf, struct abuf *obuf)
/*
* Insert silence for xrun correction
*/
- if (ibuf->r.mix.drop < 0) {
+ while (ibuf->r.mix.drop < 0) {
icount = -ibuf->r.mix.drop;
- ocount = obuf->len - obuf->used;
- if (ocount > obuf->w.mix.todo)
- ocount = obuf->w.mix.todo;
+ mix_bzero(obuf, ibuf->r.mix.done + icount);
+ ocount = obuf->w.mix.todo - ibuf->r.mix.done;
+ if (ocount == 0)
+ return 0;
scount = (icount < ocount) ? icount : ocount;
ibuf->r.mix.done += scount;
ibuf->r.mix.drop += scount;
@@ -652,6 +658,9 @@ mix_badd(struct abuf *ibuf, struct abuf *obuf)
if (ocount == 0)
return 0;
+ scount = (icount < ocount) ? icount : ocount;
+ mix_bzero(obuf, scount + ibuf->r.mix.done);
+
vol = (ibuf->r.mix.weight * ibuf->r.mix.vol) >> ADATA_SHIFT;
cmin = obuf->cmin > ibuf->cmin ? obuf->cmin : ibuf->cmin;
cmax = obuf->cmax < ibuf->cmax ? obuf->cmax : ibuf->cmax;
@@ -662,7 +671,6 @@ mix_badd(struct abuf *ibuf, struct abuf *obuf)
cc = cmax - cmin + 1;
odata += ostart;
idata += istart;
- scount = (icount < ocount) ? icount : ocount;
for (i = scount; i > 0; i--) {
for (j = cc; j > 0; j--) {
*odata += (*idata * vol) >> ADATA_SHIFT;
@@ -770,7 +778,6 @@ mix_in(struct aproc *p, struct abuf *ibuf)
#endif
if (!MIX_ROK(ibuf))
return 0;
- mix_bzero(obuf);
scount = 0;
odone = obuf->w.mix.todo;
for (i = LIST_FIRST(&p->ins); i != NULL; i = inext) {
@@ -852,9 +859,11 @@ mix_out(struct aproc *p, struct abuf *obuf)
}
#endif
maxwrite = p->u.mix.maxlat - p->u.mix.lat;
- mix_bzero(obuf);
+ if (maxwrite > obuf->w.mix.todo) {
+ if ((p->flags & (APROC_QUIT | APROC_DROP)) == APROC_DROP)
+ mix_bzero(obuf, maxwrite);
+ }
scount = 0;
- /* XXX: can obuf->len be larger than obuf->w.mix.todo ? */
odone = obuf->len;
for (i = LIST_FIRST(&p->ins); i != NULL; i = inext) {
inext = LIST_NEXT(i, ient);
@@ -871,18 +880,19 @@ mix_out(struct aproc *p, struct abuf *obuf)
if (odone > i->r.mix.done)
odone = i->r.mix.done;
}
- if (LIST_EMPTY(&p->ins)) {
+ if (LIST_EMPTY(&p->ins) && obuf->w.mix.todo == 0) {
if (p->flags & APROC_QUIT) {
aproc_del(p);
return 0;
}
if (!(p->flags & APROC_DROP))
return 0;
- odone = obuf->w.mix.todo;
}
- if (maxwrite > 0) {
- if (odone > maxwrite)
- odone = maxwrite;
+ if (odone > obuf->w.mix.todo)
+ odone = obuf->w.mix.todo;
+ if (odone > maxwrite)
+ odone = maxwrite;
+ if (odone > 0) {
p->u.mix.lat += odone;
p->u.mix.abspos += odone;
LIST_FOREACH(i, &p->ins, ient) {
@@ -1005,7 +1015,7 @@ struct aproc_ops mix_ops = {
};
struct aproc *
-mix_new(char *name, int maxlat, unsigned round, struct aproc *ctl)
+mix_new(char *name, int maxlat, unsigned round)
{
struct aproc *p;
@@ -1015,7 +1025,8 @@ mix_new(char *name, int maxlat, unsigned round, struct aproc *ctl)
p->u.mix.round = round;
p->u.mix.maxlat = maxlat;
p->u.mix.abspos = 0;
- p->u.mix.ctl = ctl;
+ p->u.mix.ctl = NULL;
+ p->u.mix.mon = NULL;
return p;
}
@@ -1086,12 +1097,12 @@ mix_prime(struct aproc *p)
if (!ABUF_WOK(obuf))
break;
todo = p->u.mix.maxlat - p->u.mix.lat;
- if (todo == 0)
- break;
- mix_bzero(obuf);
+ mix_bzero(obuf, todo);
count = obuf->w.mix.todo;
if (count > todo)
count = todo;
+ if (count == 0)
+ break;
obuf->w.mix.todo -= count;
p->u.mix.lat += count;
p->u.mix.abspos += count;
@@ -1113,6 +1124,26 @@ mix_prime(struct aproc *p)
}
/*
+ * Gracefully terminate the mixer: raise the APROC_QUIT flag
+ * and let the rest of the code do the job. If there are neither
+ * inputs nor uncommited data, then terminate right away
+ */
+void
+mix_quit(struct aproc *p)
+{
+ struct abuf *obuf = LIST_FIRST(&p->outs);
+
+ p->flags |= APROC_QUIT;
+
+ /*
+ * eof the last input will trigger aproc_del()
+ */
+ if (!LIST_EMPTY(&p->ins) || obuf->w.mix.todo > 0)
+ return;
+ aproc_del(p);
+}
+
+/*
* Append as much as possible silence on the writer end
*/
void
@@ -1434,7 +1465,7 @@ struct aproc_ops sub_ops = {
};
struct aproc *
-sub_new(char *name, int maxlat, unsigned round, struct aproc *ctl)
+sub_new(char *name, int maxlat, unsigned round)
{
struct aproc *p;
@@ -1444,7 +1475,7 @@ sub_new(char *name, int maxlat, unsigned round, struct aproc *ctl)
p->u.sub.round = round;
p->u.sub.maxlat = maxlat;
p->u.sub.abspos = 0;
- p->u.sub.ctl = ctl;
+ p->u.sub.ctl = NULL;
return p;
}
diff --git a/usr.bin/aucat/aproc.h b/usr.bin/aucat/aproc.h
index 343743b55d5..ff5b4584d62 100644
--- a/usr.bin/aucat/aproc.h
+++ b/usr.bin/aucat/aproc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: aproc.h,v 1.35 2010/04/24 06:18:23 ratchov Exp $ */
+/* $OpenBSD: aproc.h,v 1.36 2010/05/02 11:12:31 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -237,8 +237,8 @@ void aproc_opos(struct aproc *, struct abuf *, int);
struct aproc *rfile_new(struct file *);
struct aproc *wfile_new(struct file *);
-struct aproc *mix_new(char *, int, unsigned, struct aproc *);
-struct aproc *sub_new(char *, int, unsigned, struct aproc *);
+struct aproc *mix_new(char *, int, unsigned);
+struct aproc *sub_new(char *, int, unsigned);
struct aproc *resamp_new(char *, unsigned, unsigned);
struct aproc *enc_new(char *, struct aparams *);
struct aproc *dec_new(char *, struct aparams *);
@@ -262,6 +262,7 @@ int wfile_do(struct aproc *, unsigned, unsigned *);
void mix_setmaster(struct aproc *);
void mix_clear(struct aproc *);
void mix_prime(struct aproc *);
+void mix_quit(struct aproc *);
void mix_drop(struct abuf *, int);
void sub_silence(struct abuf *, int);
void sub_clear(struct aproc *);
diff --git a/usr.bin/aucat/aucat.c b/usr.bin/aucat/aucat.c
index 0ab623b116e..e7767c597cb 100644
--- a/usr.bin/aucat/aucat.c
+++ b/usr.bin/aucat/aucat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: aucat.c,v 1.88 2010/04/24 14:33:46 ratchov Exp $ */
+/* $OpenBSD: aucat.c,v 1.89 2010/05/02 11:12:31 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -356,21 +356,33 @@ privdrop(void)
}
void
-stopall(char *base)
+stopall(void)
{
struct file *f;
restart:
LIST_FOREACH(f, &file_list, entry) {
/*
- * skip connected streams (handled by dev_done())
+ * skip connected streams (handled by dev_close())
*/
- if (APROC_OK(dev_mix) && f->rproc &&
- aproc_depend(dev_mix, f->rproc))
- continue;
- if (APROC_OK(dev_sub) && f->wproc &&
- aproc_depend(f->wproc, dev_sub))
- continue;
+ if (APROC_OK(dev_mix)) {
+ if (f->rproc && aproc_depend(dev_mix, f->rproc))
+ continue;
+ if (f->wproc && aproc_depend(f->wproc, dev_mix))
+ continue;
+ }
+ if (APROC_OK(dev_sub)) {
+ if (f->rproc && aproc_depend(dev_sub, f->rproc))
+ continue;
+ if (f->wproc && aproc_depend(f->wproc, dev_sub))
+ continue;
+ }
+ if (APROC_OK(dev_submon)) {
+ if (f->rproc && aproc_depend(dev_submon, f->rproc))
+ continue;
+ if (f->wproc && aproc_depend(f->wproc, dev_submon))
+ continue;
+ }
if (APROC_OK(dev_midi)) {
if (f->rproc && aproc_depend(dev_midi, f->rproc))
continue;
@@ -743,7 +755,7 @@ aucat_main(int argc, char **argv)
dev_start();
}
}
- stopall(base);
+ stopall();
dev_done();
filelist_done();
if (l_flag) {
@@ -913,7 +925,7 @@ midicat_main(int argc, char **argv)
if (!file_poll())
break;
}
- stopall(base);
+ stopall();
dev_done();
filelist_done();
if (l_flag) {
diff --git a/usr.bin/aucat/dev.c b/usr.bin/aucat/dev.c
index c155720e5ca..e963cef8d5b 100644
--- a/usr.bin/aucat/dev.c
+++ b/usr.bin/aucat/dev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dev.c,v 1.49 2010/04/24 06:18:23 ratchov Exp $ */
+/* $OpenBSD: dev.c,v 1.50 2010/05/02 11:12:31 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -127,9 +127,9 @@ dev_loopinit(struct aparams *dipar, struct aparams *dopar, unsigned bufsz)
dev_pstate = DEV_INIT;
buf = abuf_new(dev_bufsz, &par);
- dev_mix = mix_new("mix", dev_bufsz, 1, NULL);
+ dev_mix = mix_new("mix", dev_bufsz, 1);
dev_mix->refs++;
- dev_sub = sub_new("sub", dev_bufsz, 1, NULL);
+ dev_sub = sub_new("sub", dev_bufsz, 1);
dev_sub->refs++;
aproc_setout(dev_mix, buf);
aproc_setin(dev_sub, buf);
@@ -224,9 +224,10 @@ dev_init(char *devpath, unsigned mode,
* Append a "sub" to which clients will connect.
* Link it to the controller only in record-only mode
*/
- dev_sub = sub_new("rec", dev_bufsz, dev_round,
- dopar ? NULL : dev_midi);
+ dev_sub = sub_new("rec", dev_bufsz, dev_round);
dev_sub->refs++;
+ if (!(mode & MODE_PLAY))
+ dev_sub->u.sub.ctl = dev_midi;
aproc_setin(dev_sub, buf);
} else {
dev_rec = NULL;
@@ -260,8 +261,9 @@ dev_init(char *devpath, unsigned mode,
/*
* Append a "mix" to which clients will connect.
*/
- dev_mix = mix_new("play", dev_bufsz, dev_round, dev_midi);
+ dev_mix = mix_new("play", dev_bufsz, dev_round);
dev_mix->refs++;
+ dev_mix->u.mix.ctl = dev_midi;
aproc_setout(dev_mix, buf);
} else {
dev_play = NULL;
@@ -281,7 +283,7 @@ dev_init(char *devpath, unsigned mode,
* Append a "sub" to which clients will connect.
* Link it to the controller only in record-only mode
*/
- dev_submon = sub_new("mon", dev_bufsz, dev_round, NULL);
+ dev_submon = sub_new("mon", dev_bufsz, dev_round);
dev_submon->refs++;
aproc_setin(dev_submon, buf);
@@ -318,6 +320,26 @@ dev_done(void)
{
struct file *f;
+ /*
+ * if the device is starting, ensure it actually starts
+ * so buffers are drained, else clear any buffers
+ */
+ switch (dev_pstate) {
+ case DEV_START:
+#ifdef DEBUG
+ if (debug_level >= 3)
+ dbg_puts("draining device\n");
+#endif
+ dev_start();
+ break;
+ case DEV_INIT:
+#ifdef DEBUG
+ if (debug_level >= 3)
+ dbg_puts("flushing device\n");
+#endif
+ dev_clear();
+ break;
+ }
#ifdef DEBUG
if (debug_level >= 2)
dbg_puts("closing audio device\n");
@@ -333,7 +355,8 @@ dev_done(void)
* reorder the file_list, we have to restart the loop
* after each call to file_eof().
*/
- dev_mix->flags |= APROC_QUIT;
+ if (APROC_OK(dev_mix))
+ mix_quit(dev_mix);
if (APROC_OK(dev_mix->u.mix.mon)) {
dev_mix->u.mix.mon->refs--;
aproc_del(dev_mix->u.mix.mon);