summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Ratchov <ratchov@cvs.openbsd.org>2008-06-02 17:03:26 +0000
committerAlexandre Ratchov <ratchov@cvs.openbsd.org>2008-06-02 17:03:26 +0000
commit22932c2094356d157dcfb5ad2433dabbe584f4f5 (patch)
tree55215eee405f48b1926fbee61874b6ed14b0ddf3
parentdbe2b2dca9331d0aca4c0f0da391cbc7751f0362 (diff)
Allows any input/output stream to underrun/overrun without disturbing
other streams. Beside making aucat usable with slow apps (eg. cdio), this change will ease turning aucat into an audio server later if one of the input buffers underruns, then silence is generated in place of the missing samples. Later, as many samples are dropped in order to maintain the stream in sync with the rest if one of the output buffers overruns then newer samples are discarded. Later silence is generated in order to maintain the stream in sync with the rest. ok jakemsr
-rw-r--r--usr.bin/aucat/abuf.h4
-rw-r--r--usr.bin/aucat/aproc.c63
2 files changed, 56 insertions, 11 deletions
diff --git a/usr.bin/aucat/abuf.h b/usr.bin/aucat/abuf.h
index ed0625a4328..67f8a70830a 100644
--- a/usr.bin/aucat/abuf.h
+++ b/usr.bin/aucat/abuf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: abuf.h,v 1.2 2008/05/25 21:16:37 ratchov Exp $ */
+/* $OpenBSD: abuf.h,v 1.3 2008/06/02 17:03:25 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -29,7 +29,9 @@ struct abuf {
int mixvol; /* input gain */
unsigned mixdone; /* input of mixer */
unsigned mixtodo; /* output of mixer */
+ unsigned mixdrop; /* frames mix_in() will discard */
unsigned subdone; /* output if sub */
+ unsigned subdrop; /* silence frames sub_out() will insert */
LIST_ENTRY(abuf) ient; /* for mix inputs list */
LIST_ENTRY(abuf) oent; /* for sub outputs list */
diff --git a/usr.bin/aucat/aproc.c b/usr.bin/aucat/aproc.c
index 6d3067fb936..fa060326135 100644
--- a/usr.bin/aucat/aproc.c
+++ b/usr.bin/aucat/aproc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: aproc.c,v 1.2 2008/05/25 21:16:37 ratchov Exp $ */
+/* $OpenBSD: aproc.c,v 1.3 2008/06/02 17:03:25 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -332,11 +332,26 @@ int
mix_in(struct aproc *p, struct abuf *ibuf)
{
struct abuf *i, *inext, *obuf = LIST_FIRST(&p->obuflist);
- unsigned ocount;
+ unsigned icount, ocount;
DPRINTFN(4, "mix_in: used = %u, done = %u, zero = %u\n",
ibuf->used, ibuf->mixdone, obuf->mixtodo);
+ /*
+ * discard data already sent as silence
+ */
+ if (ibuf->mixdrop > 0) {
+ icount = ibuf->mixdrop;
+ if (icount > ibuf->used)
+ icount = ibuf->used;
+ ibuf->used -= icount;
+ ibuf->start += icount;
+ if (ibuf->start >= ibuf->len)
+ ibuf->start -= ibuf->len;
+ ibuf->mixdrop -= icount;
+ DPRINTF("mix_in: catched xruns, drop = %u\n", ibuf->mixdrop);
+ }
+
if (ibuf->mixdone >= obuf->mixtodo)
return 0;
mix_badd(ibuf, obuf);
@@ -372,20 +387,22 @@ int
mix_out(struct aproc *p, struct abuf *obuf)
{
struct abuf *i, *inext;
- unsigned ocount;
+ unsigned ocount, drop;
DPRINTFN(4, "mix_out: used = %u, zero = %u\n",
obuf->used, obuf->mixtodo);
- /*
- * XXX: should handle underruns here, currently if one input is
- * blocked, then the output block can underrun.
- */
mix_bzero(p);
ocount = obuf->mixtodo;
for (i = LIST_FIRST(&p->ibuflist); i != LIST_END(&p->ibuflist); i = inext) {
inext = LIST_NEXT(i, ient);
- mix_badd(i, obuf);
+ if (!ABUF_ROK(i) && i->mixdone == 0) {
+ drop = obuf->mixtodo;
+ i->mixdone += drop;
+ i->mixdrop += drop;
+ DPRINTF("mix_out: xrun, drop = %u\n", i->mixdrop);
+ } else
+ mix_badd(i, obuf);
if (ocount > i->mixdone)
ocount = i->mixdone;
if (ABUF_EOF(i)) {
@@ -444,6 +461,7 @@ void
mix_newin(struct aproc *p, struct abuf *ibuf)
{
ibuf->mixdone = 0;
+ ibuf->mixdrop = 0;
ibuf->mixvol = ADATA_UNIT;
}
@@ -506,19 +524,26 @@ int
sub_in(struct aproc *p, struct abuf *ibuf)
{
struct abuf *i, *inext;
- unsigned done;
+ unsigned done, drop;
int again;
again = 1;
done = ibuf->used;
for (i = LIST_FIRST(&p->obuflist); i != LIST_END(&p->obuflist); i = inext) {
inext = LIST_NEXT(i, oent);
- if (ABUF_WOK(i)) {
+ if (!ABUF_WOK(i) && i->subdone == 0) {
+ drop = ibuf->used;
+ i->subdrop += drop;
+ i->subdone += drop;
+ DPRINTF("sub_in: xrun, drop = %u\n", i->subdrop);
+ } else {
sub_bcopy(ibuf, i);
abuf_flush(i);
}
+#ifdef sub_xrun_disabled
if (!ABUF_WOK(i))
again = 0;
+#endif
if (done > i->subdone)
done = i->subdone;
}
@@ -537,8 +562,25 @@ sub_out(struct aproc *p, struct abuf *obuf)
{
struct abuf *ibuf = LIST_FIRST(&p->ibuflist);
struct abuf *i, *inext;
+ unsigned char *odata;
+ unsigned ocount;
unsigned done;
+ /*
+ * generate silence for dropped samples
+ */
+ while (obuf->subdrop > 0) {
+ odata = abuf_wgetblk(obuf, &ocount, 0);
+ if (ocount >= obuf->subdrop)
+ ocount = obuf->subdrop;
+ if (ocount == 0)
+ break;
+ memset(odata, 0, ocount);
+ obuf->used += ocount;
+ obuf->subdrop -= ocount;
+ DPRINTF("sub_out: catched, drop = %u\n", obuf->subdrop);
+ }
+
if (obuf->subdone >= ibuf->used)
return 0;
@@ -611,6 +653,7 @@ void
sub_newout(struct aproc *p, struct abuf *obuf)
{
obuf->subdone = 0;
+ obuf->subdrop = 0;
}
struct aproc_ops sub_ops = {