Hi,

The diff below allows aucat to use only two audio blocks,
which lowers the server-side latency. The diff should not
impact stability, actually it should slightly improve it.
Yeah, I know, improved stablility with smaller buffers might
sound surprising...

I'd love if people could test this diff to be sure it breaks
nothing. I'm mostly interrested in sound degradation (if
any) caused by this diff.

-- Alexandre

Index: aproc.c
===================================================================
RCS file: /home/alex/mio/cvs/src/usr.bin/aucat/aproc.c,v
retrieving revision 1.18
diff -u -p -r1.18 aproc.c
--- aproc.c     16 Jan 2010 13:50:23 -0000      1.18
+++ aproc.c     16 Jan 2010 15:36:55 -0000
@@ -625,6 +625,7 @@ mix_in(struct aproc *p, struct abuf *ibu
 {
        struct abuf *i, *inext, *obuf = LIST_FIRST(&p->obuflist);
        unsigned odone;
+       unsigned maxwrite;
 
 #ifdef DEBUG
        if (debug_level >= 4) {
@@ -642,7 +643,24 @@ mix_in(struct aproc *p, struct abuf *ibu
 #endif
        if (!ABUF_ROK(ibuf))
                return 0;
+       maxwrite = (p->u.mix.maxlat - p->u.mix.lat) * obuf->bpf;
+#ifdef DEBUG
+       if (debug_level >= 4) {
+               aproc_dbg(p);
+               dbg_puts(": maxwrite = ");
+               dbg_putu(p->u.mix.maxlat);
+               dbg_puts(" - ");
+               dbg_putu(p->u.mix.lat);
+               dbg_puts(" = ");
+               dbg_putu(p->u.mix.maxlat - p->u.mix.lat);
+               dbg_puts("\n");
+       }
+#endif
+       if (maxwrite == 0)
+               return 0;
        odone = obuf->len;
+       if (odone > maxwrite)
+               odone = maxwrite;
        for (i = LIST_FIRST(&p->ibuflist); i != NULL; i = inext) {
                inext = LIST_NEXT(i, ient);
                if (!abuf_fill(i))
@@ -669,6 +687,7 @@ mix_out(struct aproc *p, struct abuf *ob
 {
        struct abuf *i, *inext;
        unsigned odone;
+       unsigned maxwrite;
 
 #ifdef DEBUG
        if (debug_level >= 4) {
@@ -686,6 +705,24 @@ mix_out(struct aproc *p, struct abuf *ob
 #endif
        if (!ABUF_WOK(obuf))
                return 0;
+       maxwrite = (p->u.mix.maxlat - p->u.mix.lat) * obuf->bpf;
+#ifdef DEBUG
+       if (debug_level >= 4) {
+               aproc_dbg(p);
+               dbg_puts(": maxwrite = ");
+               dbg_putu(p->u.mix.maxlat);
+               dbg_puts(" - ");
+               dbg_putu(p->u.mix.lat);
+               dbg_puts(" = ");
+               dbg_putu(p->u.mix.maxlat - p->u.mix.lat);
+               dbg_puts("\n");
+       }
+#endif
+       if (maxwrite == 0)
+               return 0;
+       odone = obuf->len;
+       if (odone > maxwrite)
+               odone = maxwrite;
        odone = obuf->len;
        for (i = LIST_FIRST(&p->ibuflist); i != NULL; i = inext) {
                inext = LIST_NEXT(i, ient);
@@ -800,6 +837,7 @@ mix_newout(struct aproc *p, struct abuf 
 void
 mix_opos(struct aproc *p, struct abuf *obuf, int delta)
 {
+       p->u.mix.lat -= delta;
 #ifdef DEBUG
        if (debug_level >= 4) {
                aproc_dbg(p);
@@ -810,7 +848,6 @@ mix_opos(struct aproc *p, struct abuf *o
                dbg_puts(" fr\n");
        }
 #endif
-       p->u.mix.lat -= delta;
        if (p->u.mix.ctl)
                ctl_ontick(p->u.mix.ctl, delta);
        aproc_opos(p, obuf, delta);
Index: aproc.h
===================================================================
RCS file: /home/alex/mio/cvs/src/usr.bin/aucat/aproc.h,v
retrieving revision 1.18
diff -u -p -r1.18 aproc.h
--- aproc.h     11 Jan 2010 16:01:16 -0000      1.18
+++ aproc.h     16 Jan 2010 13:51:54 -0000
@@ -210,6 +210,9 @@ void aproc_setin(struct aproc *, struct 
 void aproc_setout(struct aproc *, struct abuf *);
 int aproc_depend(struct aproc *, struct aproc *);
 
+void aproc_ipos(struct aproc *, struct abuf *, int);
+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, struct aproc *);
@@ -218,6 +221,18 @@ struct aproc *resamp_new(char *, unsigne
 struct aproc *cmap_new(char *, struct aparams *, struct aparams *);
 struct aproc *enc_new(char *, struct aparams *);
 struct aproc *dec_new(char *, struct aparams *);
+
+int rfile_in(struct aproc *, struct abuf *);
+int rfile_out(struct aproc *, struct abuf *);
+void rfile_eof(struct aproc *, struct abuf *);
+void rfile_hup(struct aproc *, struct abuf *);
+void rfile_done(struct aproc *);
+
+int wfile_in(struct aproc *, struct abuf *);
+int wfile_out(struct aproc *, struct abuf *);
+void wfile_eof(struct aproc *, struct abuf *);
+void wfile_hup(struct aproc *, struct abuf *);
+void wfile_done(struct aproc *);
 
 void mix_setmaster(struct aproc *);
 void mix_clear(struct aproc *);
Index: dev.c
===================================================================
RCS file: /home/alex/mio/cvs/src/usr.bin/aucat/dev.c,v
retrieving revision 1.18
diff -u -p -r1.18 dev.c
--- dev.c       13 Jan 2010 10:13:43 -0000      1.18
+++ dev.c       16 Jan 2010 13:51:54 -0000
@@ -147,7 +147,7 @@ dev_init(char *devpath,
        struct aparams ipar, opar;
        struct aproc *conv;
        struct abuf *buf;
-       unsigned nfr, ibufsz, obufsz;
+       unsigned nfr;
 
        dev_midi = ctl_new("ctl");
        dev_midi->refs++;
@@ -157,8 +157,10 @@ dev_init(char *devpath,
         * limit the block size to 1/4 of the requested buffer.
         */
        dev_round = round;
-       dev_bufsz = (bufsz + 3) / 4 + (dev_round - 1);
+       dev_bufsz = bufsz + (round - 1);
        dev_bufsz -= dev_bufsz % dev_round;
+       if (dev_bufsz < dev_round)
+               dev_bufsz = dev_round;
        f = (struct file *)siofile_new(&siofile_ops, devpath,
            dipar, dopar, &dev_bufsz, &dev_round);
        if (f == NULL)
@@ -183,7 +185,6 @@ dev_init(char *devpath,
 #endif
                dev_rate = dopar->rate;
        }
-       ibufsz = obufsz = dev_bufsz;
        bufsz = (bufsz > dev_bufsz) ? bufsz - dev_bufsz : 0;
 
        /*
@@ -205,11 +206,10 @@ dev_init(char *devpath,
                /*
                 * Create the read end.
                 */
-               dev_rec = rfile_new(f);
+               dev_rec = rsio_new(f);
                dev_rec->refs++;
                buf = abuf_new(nfr, dipar);
                aproc_setout(dev_rec, buf);
-               ibufsz += nfr;
 
                /*
                 * Append a converter, if needed.
@@ -219,7 +219,6 @@ dev_init(char *devpath,
                        aproc_setin(conv, buf);
                        buf = abuf_new(nfr, &ipar);
                        aproc_setout(conv, buf);
-                       ibufsz += nfr;
                }
                dev_ipar = ipar;
 
@@ -227,7 +226,7 @@ dev_init(char *devpath,
                 * Append a "sub" to which clients will connect.
                 * Link it to the controller only in record-only mode
                 */
-               dev_sub = sub_new("rec", ibufsz, dopar ? NULL : dev_midi);
+               dev_sub = sub_new("rec", dev_bufsz, dopar ? NULL : dev_midi);
                dev_sub->refs++;
                aproc_setin(dev_sub, buf);
        } else {
@@ -243,11 +242,10 @@ dev_init(char *devpath,
                /*
                 * Create the write end.
                 */
-               dev_play = wfile_new(f);
+               dev_play = wsio_new(f);
                dev_play->refs++;
                buf = abuf_new(nfr, dopar);
                aproc_setin(dev_play, buf);
-               obufsz += nfr;
 
                /*
                 * Append a converter, if needed.
@@ -257,21 +255,19 @@ dev_init(char *devpath,
                        aproc_setout(conv, buf);
                        buf = abuf_new(nfr, &opar);
                        aproc_setin(conv, buf);
-                       obufsz += nfr;
                }
                dev_opar = opar;
 
                /*
                 * Append a "mix" to which clients will connect.
                 */
-               dev_mix = mix_new("play", obufsz, dev_midi);
+               dev_mix = mix_new("play", dev_bufsz, dev_midi);
                dev_mix->refs++;
                aproc_setout(dev_mix, buf);
        } else {
                dev_play = NULL;
                dev_mix = NULL;
        }
-       dev_bufsz = (dopar) ? obufsz : ibufsz;
 #ifdef DEBUG
        if (debug_level >= 2) {
                dbg_puts("device block size is ");
Index: siofile.c
===================================================================
RCS file: /home/alex/mio/cvs/src/usr.bin/aucat/siofile.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 siofile.c
--- siofile.c   13 Jan 2010 10:08:15 -0000      1.1.1.1
+++ siofile.c   16 Jan 2010 13:51:54 -0000
@@ -26,6 +26,7 @@
 
 #include "aparams.h"
 #include "aproc.h"
+#include "abuf.h"
 #include "conf.h"
 #include "dev.h"
 #include "file.h"
@@ -37,6 +38,7 @@
 struct siofile {
        struct file file;
        struct sio_hdl *hdl;
+       unsigned tickets, bpf, bufsz;
        int started;
 };
 
@@ -62,6 +64,73 @@ struct fileops siofile_ops = {
        siofile_revents
 };
 
+int wsio_out(struct aproc *, struct abuf *);
+
+struct aproc_ops rsio_ops = {
+       "rsio",
+       rfile_in,
+       rfile_out,
+       rfile_eof,
+       rfile_hup,
+       NULL, /* newin */
+       NULL, /* newout */
+       aproc_ipos,
+       aproc_opos,
+       rfile_done
+};
+
+struct aproc_ops wsio_ops = {
+       "wsio",
+       wfile_in,
+       wsio_out,
+       wfile_eof,
+       wfile_hup,
+       NULL, /* newin */
+       NULL, /* newout */
+       aproc_ipos,
+       aproc_opos,
+       wfile_done
+};
+
+struct aproc *
+rsio_new(struct file *f)
+{
+       struct aproc *p;
+
+       p = aproc_new(&rsio_ops, f->name);
+       p->u.io.file = f;
+       f->rproc = p;
+       return p;
+}
+
+struct aproc *
+wsio_new(struct file *f)
+{
+       struct aproc *p;
+
+       p = aproc_new(&wsio_ops, f->name);
+       p->u.io.file = f;
+       f->wproc = p;
+       return p;
+}
+
+int
+wsio_out(struct aproc *p, struct abuf *obuf)
+{
+       struct siofile *f = (struct siofile *)p->u.io.file;
+
+       if (f->tickets == 0) {
+#ifdef DEBUG
+               if (debug_level >= 4) {
+                       file_dbg(&f->file);
+                       dbg_puts(": no more tickets\n");
+               }
+#endif
+               return 0;
+       }
+       return wfile_out(p, obuf);
+}
+
 void
 siofile_cb(void *addr, int delta)
 {
@@ -70,12 +139,18 @@ siofile_cb(void *addr, int delta)
 
 #ifdef DEBUG
        if (delta < 0 || delta > (60 * RATE_MAX)) {
-               dbg_puts(f->file.name);
+               file_dbg(&f->file);
                dbg_puts(": ");
                dbg_puti(delta);
                dbg_puts(": bogus sndio delta");
                dbg_panic();
        }
+       if (debug_level >= 4) {
+               file_dbg(&f->file);
+               dbg_puts(": tick, delta = ");
+               dbg_puti(delta);
+               dbg_puts("\n");
+       }
 #endif
        if (delta != 0) {
                p = f->file.wproc;
@@ -87,6 +162,9 @@ siofile_cb(void *addr, int delta)
                if (p && p->ops->ipos)
                        p->ops->ipos(p, NULL, delta);
        }
+       f->tickets += delta * f->bpf;
+       if (f->file.state & FILE_WOK)
+               f->file.state &= ~FILE_WOK;
 }
 
 /*
@@ -162,6 +240,9 @@ siofile_new(struct fileops *ops, char *p
                goto bad_close;
        f->hdl = hdl;
        f->started = 0;
+       f->tickets = 0;
+       f->bufsz = par.bufsz;
+       f->bpf = par.pchan * par.bps;
        sio_onmove(f->hdl, siofile_cb, f);
        return f;
  bad_close:
@@ -183,6 +264,7 @@ siofile_start(struct file *file)
                return;
        }
        f->started = 1;
+       f->tickets = f->bufsz * f->bpf;
 #ifdef DEBUG
        if (debug_level >= 3) {
                file_dbg(&f->file);
@@ -248,6 +330,8 @@ siofile_write(struct file *file, unsigne
        struct siofile *f = (struct siofile *)file;
        unsigned n;
 
+       if (count > f->tickets)
+               count = f->tickets;
        n = f->started ? sio_write(f->hdl, data, count) : 0;
        if (n == 0) {
                f->file.state &= ~FILE_WOK;
@@ -266,7 +350,8 @@ siofile_write(struct file *file, unsigne
 #endif
                }
                return 0;
-       }
+       } else
+               f->tickets -= count;
        return n;
 }
 
Index: siofile.h
===================================================================
RCS file: /home/alex/mio/cvs/src/usr.bin/aucat/siofile.h,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 siofile.h
--- siofile.h   13 Jan 2010 10:08:16 -0000      1.1.1.1
+++ siofile.h   16 Jan 2010 13:51:54 -0000
@@ -20,9 +20,12 @@
 struct fileops;
 struct siofile;
 struct aparams;
+struct aproc;
 
 struct siofile *siofile_new(struct fileops *, char *,
     struct aparams *, struct aparams *, unsigned *, unsigned *);
+struct aproc *rsio_new(struct file *f);
+struct aproc *wsio_new(struct file *f);
 
 extern struct fileops siofile_ops;

Reply via email to