summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorAlexandre Ratchov <ratchov@cvs.openbsd.org>2010-05-02 11:12:32 +0000
committerAlexandre Ratchov <ratchov@cvs.openbsd.org>2010-05-02 11:12:32 +0000
commitaa21ef7541a3118da61e9f0b759077a58b9d0f00 (patch)
treeb35dec178e979b1035dbcfeb23775c733cae8a15 /usr.bin
parent7be854c95ab4dfa991a51276b596cacb6a2e4b90 (diff)
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.
Diffstat (limited to 'usr.bin')
-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);