move mix/sub underrun/overrun handling code and data in the
authorratchov <ratchov@openbsd.org>
Thu, 14 Aug 2008 09:44:15 +0000 (09:44 +0000)
committerratchov <ratchov@openbsd.org>
Thu, 14 Aug 2008 09:44:15 +0000 (09:44 +0000)
generic abuf structure, so it can reused. Required for an audio
server. No behaviour change.

ok jakemsr

usr.bin/aucat/abuf.c
usr.bin/aucat/abuf.h
usr.bin/aucat/aproc.c

index a3143d9..a6f2ebc 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: abuf.c,v 1.3 2008/08/14 09:39:16 ratchov Exp $        */
+/*     $OpenBSD: abuf.c,v 1.4 2008/08/14 09:44:15 ratchov Exp $        */
 /*
  * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
  *
@@ -36,6 +36,7 @@
 #include <err.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include "conf.h"
 #include "aproc.h"
@@ -60,6 +61,8 @@ abuf_new(unsigned nfr, unsigned bpf)
        buf->len = len;
        buf->used = 0;
        buf->start = 0;
+       buf->silence = 0;
+       buf->drop = 0;
        buf->rproc = NULL;
        buf->wproc = NULL;
        buf->data = (unsigned char *)buf + sizeof(*buf);
@@ -150,6 +153,31 @@ abuf_wgetblk(struct abuf *buf, unsigned *rsize, unsigned ofs)
        return buf->data + end;
 }
 
+/*
+ * flush buffer either by dropping samples or by calling the aproc
+ * call-back to consume data. Return 0 if blocked, 1 otherwise
+ */
+int
+abuf_flush_do(struct abuf *buf)
+{
+       struct aproc *p;
+       unsigned count;
+
+       if (buf->drop > 0) {
+               count = buf->drop;
+               if (count > buf->used)
+                       count = buf->used;
+               abuf_rdiscard(buf, count);
+               buf->drop -= count;
+               DPRINTF("abuf_flush_do: drop = %u\n", buf->drop);
+       } else {
+               p = buf->rproc;
+               if (p == NULL || !p->ops->in(p, buf))
+                       return 0;
+       }
+       return 1;
+}
+
 /*
  * Notify the read end of the buffer that there is input available
  * and that data can be processed again.
@@ -157,16 +185,41 @@ abuf_wgetblk(struct abuf *buf, unsigned *rsize, unsigned ofs)
 void
 abuf_flush(struct abuf *buf)
 {
-       struct aproc *p = buf->rproc;
-
        for (;;) {
                if (!ABUF_ROK(buf))
                        break;
-               if (p == NULL || !p->ops->in(p, buf))
+               if (!abuf_flush_do(buf))
                        break;
        }
 }
 
+/*
+ * fill the buffer either by generating silence or by calling the aproc
+ * call-back to provide data. Return 0 if blocked, 1 otherwise
+ */
+int
+abuf_fill_do(struct abuf *buf)
+{
+       struct aproc *p;
+       unsigned char *data;
+       unsigned count;
+
+       if (buf->silence > 0) {
+               data = abuf_wgetblk(buf, &count, 0);
+               if (count >= buf->silence)
+                       count = buf->silence;
+               memset(data, 0, count);
+               abuf_wcommit(buf, count);
+               buf->silence -= count;
+               DPRINTF("abuf_fill_do: silence = %u\n", buf->silence);
+       } else {
+               p = buf->wproc;
+               if (p == NULL || !p->ops->out(p, buf))
+                       return 0;
+       }
+       return 1;
+}
+
 /*
  * Notify the write end of the buffer that there is room and data can be
  * written again. This routine can only be called from the out()
@@ -178,12 +231,10 @@ abuf_flush(struct abuf *buf)
 void
 abuf_fill(struct abuf *buf)
 {
-       struct aproc *p = buf->wproc;
-
        for (;;) {
                if (!ABUF_WOK(buf))
                        break;
-               if (p == NULL || !p->ops->out(p, buf))
+               if (!abuf_fill_do(buf))
                        break;
        }
 }
@@ -211,12 +262,10 @@ abuf_run(struct abuf *buf)
                        abuf_del(buf);
                        return;
                }
-               if (ABUF_WOK(buf) && canfill && buf->wproc) {
-                       p = buf->wproc;
-                       canfill = p->ops->out(p, buf);
+               if (ABUF_WOK(buf) && canfill) {
+                       canfill = abuf_fill_do(buf);
                } else if (ABUF_ROK(buf) && canflush) {
-                       p = buf->rproc;
-                       canflush = p->ops->in(p, buf);
+                       canflush = abuf_flush_do(buf);
                } else
                        break; /* can neither read nor write */
        }
index d7345e0..860a6c5 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: abuf.h,v 1.5 2008/08/14 09:39:16 ratchov Exp $        */
+/*     $OpenBSD: abuf.h,v 1.6 2008/08/14 09:44:15 ratchov Exp $        */
 /*
  * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
  *
@@ -34,9 +34,7 @@ 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 */ 
 #define XRUN_IGNORE    0       /* on xrun silently insert/discard samples */
 #define XRUN_SYNC      1       /* catchup to sync to the mix/sub */
 #define XRUN_ERROR     2       /* xruns are errors, eof/hup buffer */
@@ -51,9 +49,11 @@ struct abuf {
        unsigned start;         /* offset where data starts */
        unsigned used;          /* valid data */
        unsigned len;           /* size of the ring */
+       unsigned silence;       /* silence to insert on next write */
+       unsigned drop;          /* frames to drop on next read */
        struct aproc *rproc;    /* reader */
        struct aproc *wproc;    /* writer */
-       unsigned char *data;    /* pointer to actual data (immediately following) */
+       unsigned char *data;    /* actual data (immediately following) */
 };
 
 /*
index b938bb6..b989590 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: aproc.c,v 1.6 2008/08/14 09:39:16 ratchov Exp $       */
+/*     $OpenBSD: aproc.c,v 1.7 2008/08/14 09:44:15 ratchov Exp $       */
 /*
  * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
  *
@@ -320,25 +320,10 @@ int
 mix_in(struct aproc *p, struct abuf *ibuf)
 {
        struct abuf *i, *inext, *obuf = LIST_FIRST(&p->obuflist);
-       unsigned icount, ocount;
+       unsigned ocount;
 
-       DPRINTFN(4, "mix_in: used = %u, done = %u, zero = %u\n",
+       DPRINTFN(4, "mix_in: used = %u, done = %u, todo = %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;
@@ -394,9 +379,8 @@ mix_out(struct aproc *p, struct abuf *obuf)
                                drop = obuf->mixtodo;
                                i->mixdone += drop;
                                if (i->xrun == XRUN_SYNC)
-                                       i->mixdrop += drop;
-                               DPRINTF("mix_out: xrun, drop = %u\n", 
-                                   i->mixdrop);
+                                       i->drop += drop;
+                               DPRINTF("mix_out: drop = %u\n", i->drop);
                        }
                } else
                        mix_badd(i, obuf);
@@ -458,7 +442,6 @@ void
 mix_newin(struct aproc *p, struct abuf *ibuf)
 {
        ibuf->mixdone = 0;
-       ibuf->mixdrop = 0;
        ibuf->mixvol = ADATA_UNIT;
        ibuf->xrun = XRUN_IGNORE;
 }
@@ -539,10 +522,9 @@ sub_in(struct aproc *p, struct abuf *ibuf)
                                }
                                drop = ibuf->used;
                                if (i->xrun == XRUN_SYNC)
-                                       i->subdrop += drop;
+                                       i->silence += drop;
                                i->subdone += drop;
-                               DPRINTF("sub_in: xrun, drop =  %u\n",
-                                   i->subdrop);
+                               DPRINTF("sub_in: silence =  %u\n", i->silence);
                        }
                } else {
                        sub_bcopy(ibuf, i);
@@ -565,25 +547,8 @@ 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: catch, drop = %u\n", obuf->subdrop);
-       }
-
        if (obuf->subdone >= ibuf->used)
                return 0;
 
@@ -653,7 +618,6 @@ void
 sub_newout(struct aproc *p, struct abuf *obuf)
 {
        obuf->subdone = 0;
-       obuf->subdrop = 0;
        obuf->xrun = XRUN_IGNORE;
 }