diff options
author | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2008-11-03 22:25:14 +0000 |
---|---|---|
committer | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2008-11-03 22:25:14 +0000 |
commit | 723c50cd1bb9337248bbd2997f9df971990edea2 (patch) | |
tree | 3c94418e6656ca04915ff70d6c17fc7f6d4aa12e /usr.bin | |
parent | 4aa23092c2f9e39b46581c898a9fd591b6c8a754 (diff) |
A small optimization: handle most N-channel <-> M-channel conversions
inside the mixer and the demultiplexer. This way, aucat will not
trigger the heavy conversion code when only channel conversions are
required. Cuts ~50% of the CPU usage on envy(4) devices, can improve
surround 4.0, 5.1 and 7.1 capable devices. No functionnal change.
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/aucat/abuf.c | 10 | ||||
-rw-r--r-- | usr.bin/aucat/abuf.h | 12 | ||||
-rw-r--r-- | usr.bin/aucat/aparams.c | 45 | ||||
-rw-r--r-- | usr.bin/aucat/aparams.h | 5 | ||||
-rw-r--r-- | usr.bin/aucat/aproc.c | 72 | ||||
-rw-r--r-- | usr.bin/aucat/aucat.c | 6 | ||||
-rw-r--r-- | usr.bin/aucat/dev.c | 26 | ||||
-rw-r--r-- | usr.bin/aucat/sock.c | 6 |
8 files changed, 129 insertions, 53 deletions
diff --git a/usr.bin/aucat/abuf.c b/usr.bin/aucat/abuf.c index 61a18a17293..c15b138ad31 100644 --- a/usr.bin/aucat/abuf.c +++ b/usr.bin/aucat/abuf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: abuf.c,v 1.7 2008/10/26 08:49:43 ratchov Exp $ */ +/* $OpenBSD: abuf.c,v 1.8 2008/11/03 22:25:13 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -38,6 +38,7 @@ #include <stdarg.h> #include "conf.h" +#include "aparams.h" #include "aproc.h" #include "abuf.h" @@ -63,11 +64,12 @@ abuf_dprn(int n, struct abuf *buf, char *fmt, ...) #endif struct abuf * -abuf_new(unsigned nfr, unsigned bpf) +abuf_new(unsigned nfr, struct aparams *par) { struct abuf *buf; - unsigned len; + unsigned len, bpf; + bpf = aparams_bpf(par); len = nfr * bpf; buf = malloc(sizeof(struct abuf) + len); if (buf == NULL) { @@ -75,6 +77,8 @@ abuf_new(unsigned nfr, unsigned bpf) abort(); } buf->bpf = bpf; + buf->cmin = par->cmin; + buf->cmax = par->cmax; buf->inuse = 0; /* diff --git a/usr.bin/aucat/abuf.h b/usr.bin/aucat/abuf.h index aefe8698fb8..ae1ab690c68 100644 --- a/usr.bin/aucat/abuf.h +++ b/usr.bin/aucat/abuf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: abuf.h,v 1.9 2008/10/26 08:49:43 ratchov Exp $ */ +/* $OpenBSD: abuf.h,v 1.10 2008/11/03 22:25:13 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -21,6 +21,7 @@ struct abuf; struct aproc; +struct aparam; struct abuf { /* @@ -32,9 +33,9 @@ struct abuf { * intput->output path. */ int mixvol; /* input gain */ - unsigned mixdone; /* input of mixer */ - unsigned mixtodo; /* output of mixer */ - unsigned subdone; /* output if sub */ + unsigned mixdone; /* input already processed */ + unsigned mixtodo; /* output not yet complete */ + unsigned subdone; /* output already processed */ #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 */ @@ -46,6 +47,7 @@ struct abuf { * fifo parameters */ unsigned bpf; /* bytes per frame */ + unsigned cmin, cmax; /* channel range of this buf */ unsigned start; /* offset where data starts */ unsigned used; /* valid data */ unsigned len; /* size of the ring */ @@ -92,7 +94,7 @@ struct abuf { */ #define ABUF_EMPTY(b) ((b)->used == 0) -struct abuf *abuf_new(unsigned, unsigned); +struct abuf *abuf_new(unsigned, struct aparams *); void abuf_del(struct abuf *); unsigned char *abuf_rgetblk(struct abuf *, unsigned *, unsigned); unsigned char *abuf_wgetblk(struct abuf *, unsigned *, unsigned); diff --git a/usr.bin/aucat/aparams.c b/usr.bin/aucat/aparams.c index 40cc9cd7fb3..2ee1b4d763e 100644 --- a/usr.bin/aucat/aparams.c +++ b/usr.bin/aucat/aparams.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aparams.c,v 1.2 2008/10/26 08:49:43 ratchov Exp $ */ +/* $OpenBSD: aparams.c,v 1.3 2008/11/03 22:25:13 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -183,17 +183,14 @@ aparams_print2(struct aparams *par1, struct aparams *par2) } /* - * Return true if both parameters are the same. + * Return true if both encodings are the same. */ int -aparams_eq(struct aparams *par1, struct aparams *par2) +aparams_eqenc(struct aparams *par1, struct aparams *par2) { if (par1->bps != par2->bps || par1->bits != par2->bits || - par1->sig != par2->sig || - par1->cmin != par2->cmin || - par1->cmax != par2->cmax || - par1->rate != par2->rate) + par1->sig != par2->sig) return 0; if ((par1->bits != 8 * par1->bps) && par1->msb != par2->msb) return 0; @@ -203,6 +200,40 @@ aparams_eq(struct aparams *par1, struct aparams *par2) } /* + * Return true if both parameters are the same. + */ +int +aparams_eq(struct aparams *par1, struct aparams *par2) +{ + if (!aparams_eqenc(par1, par2) || + par1->cmin != par2->cmin || + par1->cmax != par2->cmax || + par1->rate != par2->rate) + return 0; + return 1; +} + +/* + * Retrurn true if first channel range includes second range + */ +int +aparams_subset(struct aparams *subset, struct aparams *set) +{ + return subset->cmin >= set->cmin && subset->cmax <= set->cmax; +} + +/* + * Return true if rates are the same + */ +int +aparams_eqrate(struct aparams *p1, struct aparams *p2) +{ + /* XXX: allow 1/9 halftone of difference */ + return p1->rate == p2->rate; +} + + +/* * Return the number of bytes per frame with the given parameters. */ unsigned diff --git a/usr.bin/aucat/aparams.h b/usr.bin/aucat/aparams.h index 8d394502229..1e226f44899 100644 --- a/usr.bin/aucat/aparams.h +++ b/usr.bin/aucat/aparams.h @@ -1,4 +1,4 @@ -/* $OpenBSD: aparams.h,v 1.2 2008/10/26 08:49:43 ratchov Exp $ */ +/* $OpenBSD: aparams.h,v 1.3 2008/11/03 22:25:13 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -72,7 +72,10 @@ struct aparams { void aparams_init(struct aparams *, unsigned, unsigned, unsigned); void aparams_print(struct aparams *); void aparams_print2(struct aparams *, struct aparams *); +int aparams_eqrate(struct aparams *, struct aparams *); +int aparams_eqenc(struct aparams *, struct aparams *); int aparams_eq(struct aparams *, struct aparams *); +int aparams_subset(struct aparams *, struct aparams *); unsigned aparams_bpf(struct aparams *); int aparams_strtoenc(struct aparams *, char *); int aparams_enctostr(struct aparams *, char *); diff --git a/usr.bin/aucat/aproc.c b/usr.bin/aucat/aproc.c index 527a874042d..bf619514662 100644 --- a/usr.bin/aucat/aproc.c +++ b/usr.bin/aucat/aproc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aproc.c,v 1.12 2008/10/26 08:49:43 ratchov Exp $ */ +/* $OpenBSD: aproc.c,v 1.13 2008/11/03 22:25:13 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -348,30 +348,38 @@ void mix_badd(struct abuf *ibuf, struct abuf *obuf) { short *idata, *odata; - unsigned i, scount, icount, ocount; int vol = ibuf->mixvol; + unsigned i, j, icnt, onext, ostart; + unsigned scount, icount, ocount; DPRINTFN(4, "mix_badd: todo = %u, done = %u\n", obuf->mixtodo, ibuf->mixdone); idata = (short *)abuf_rgetblk(ibuf, &icount, 0); - icount -= icount % ibuf->bpf; + icount /= ibuf->bpf; if (icount == 0) return; odata = (short *)abuf_wgetblk(obuf, &ocount, ibuf->mixdone); - ocount -= ocount % obuf->bpf; + ocount /= obuf->bpf; if (ocount == 0) return; + ostart = ibuf->cmin - obuf->cmin; + onext = obuf->cmax - ibuf->cmax + ostart; + icnt = ibuf->cmax - ibuf->cmin + 1; + odata += ostart; scount = (icount < ocount) ? icount : ocount; - for (i = scount / sizeof(short); i > 0; i--) { - *odata += (*idata * vol) >> ADATA_SHIFT; - idata++; - odata++; - } - abuf_rdiscard(ibuf, scount); - ibuf->mixdone += scount; + for (i = scount; i > 0; i--) { + for (j = icnt; j > 0; j--) { + *odata += (*idata * vol) >> ADATA_SHIFT; + idata++; + odata++; + } + odata += onext; + } + abuf_rdiscard(ibuf, scount * ibuf->bpf); + ibuf->mixdone += scount * obuf->bpf; DPRINTFN(4, "mix_badd: added %u, done = %u, todo = %u\n", scount, ibuf->mixdone, obuf->mixtodo); @@ -509,6 +517,12 @@ mix_hup(struct aproc *p, struct abuf *obuf) void mix_newin(struct aproc *p, struct abuf *ibuf) { + struct abuf *obuf = LIST_FIRST(&p->obuflist); + + if (!obuf || ibuf->cmin < obuf->cmin || ibuf->cmax > obuf->cmax) { + fprintf(stderr, "mix_newin: channel ranges mismatch\n"); + abort(); + } ibuf->mixdone = 0; ibuf->mixvol = ADATA_UNIT; ibuf->xrun = XRUN_IGNORE; @@ -589,22 +603,34 @@ mix_setmaster(struct aproc *p) void sub_bcopy(struct abuf *ibuf, struct abuf *obuf) { - unsigned char *idata, *odata; + short *idata, *odata; + unsigned i, j, ocnt, inext, istart; unsigned icount, ocount, scount; - idata = abuf_rgetblk(ibuf, &icount, obuf->subdone); - icount -= icount % ibuf->bpf; + idata = (short *)abuf_rgetblk(ibuf, &icount, obuf->subdone); + icount /= ibuf->bpf; if (icount == 0) return; - odata = abuf_wgetblk(obuf, &ocount, 0); - ocount -= icount % obuf->bpf; + odata = (short *)abuf_wgetblk(obuf, &ocount, 0); + ocount /= obuf->bpf; if (ocount == 0) return; + istart = obuf->cmin - ibuf->cmin; + inext = ibuf->cmax - obuf->cmax + istart; + ocnt = obuf->cmax - obuf->cmin + 1; scount = (icount < ocount) ? icount : ocount; - memcpy(odata, idata, scount); - abuf_wcommit(obuf, scount); - obuf->subdone += scount; - DPRINTFN(4, "sub_bcopy: %u bytes\n", scount); + idata += istart; + for (i = scount; i > 0; i--) { + for (j = ocnt; j > 0; j--) { + *odata = *idata; + odata++; + idata++; + } + idata += inext; + } + abuf_wcommit(obuf, scount * obuf->bpf); + obuf->subdone += scount * ibuf->bpf; + DPRINTFN(4, "sub_bcopy: %u frames\n", scount); } int @@ -713,6 +739,12 @@ sub_hup(struct aproc *p, struct abuf *obuf) void sub_newout(struct aproc *p, struct abuf *obuf) { + struct abuf *ibuf = LIST_FIRST(&p->ibuflist); + + if (!ibuf || obuf->cmin < ibuf->cmin || obuf->cmax > ibuf->cmax) { + fprintf(stderr, "sub_newout: channel ranges mismatch\n"); + abort(); + } obuf->subdone = 0; obuf->xrun = XRUN_IGNORE; } diff --git a/usr.bin/aucat/aucat.c b/usr.bin/aucat/aucat.c index 22757cc9d75..5e41f46c65a 100644 --- a/usr.bin/aucat/aucat.c +++ b/usr.bin/aucat/aucat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aucat.c,v 1.30 2008/10/26 12:38:38 ratchov Exp $ */ +/* $OpenBSD: aucat.c,v 1.31 2008/11/03 22:25:13 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -239,7 +239,7 @@ newinput(struct farg *fa) */ f = wav_new_in(&wav_ops, fd, fa->name, &fa->par, fa->hdr); nfr = dev_bufsz * fa->par.rate / dev_rate; - buf = abuf_new(nfr, aparams_bpf(&fa->par)); + buf = abuf_new(nfr, &fa->par); proc = rpipe_new((struct file *)f); aproc_setout(proc, buf); abuf_fill(buf); /* XXX: move this in dev_attach() ? */ @@ -275,7 +275,7 @@ newoutput(struct farg *fa) f = wav_new_out(&wav_ops, fd, fa->name, &fa->par, fa->hdr); nfr = dev_bufsz * fa->par.rate / dev_rate; proc = wpipe_new((struct file *)f); - buf = abuf_new(nfr, aparams_bpf(&fa->par)); + buf = abuf_new(nfr, &fa->par); aproc_setin(proc, buf); dev_attach(fa->name, NULL, NULL, 0, buf, &fa->par, fa->xrun); } diff --git a/usr.bin/aucat/dev.c b/usr.bin/aucat/dev.c index 0f418a63fc8..70391760653 100644 --- a/usr.bin/aucat/dev.c +++ b/usr.bin/aucat/dev.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dev.c,v 1.3 2008/10/26 08:49:43 ratchov Exp $ */ +/* $OpenBSD: dev.c,v 1.4 2008/11/03 22:25:13 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -138,14 +138,14 @@ dev_init(char *devpath, * create the read end */ dev_rec = rpipe_new(dev_file); - buf = abuf_new(nfr, aparams_bpf(dipar)); + buf = abuf_new(nfr, dipar); aproc_setout(dev_rec, buf); ibufsz += nfr; /* * append a converter, if needed */ - if (!aparams_eq(dipar, &ipar)) { + if (!aparams_eqenc(dipar, &ipar)) { if (debug_level > 0) { fprintf(stderr, "%s: ", devpath); aparams_print2(dipar, &ipar); @@ -153,7 +153,7 @@ dev_init(char *devpath, } conv = conv_new("subconv", dipar, &ipar); aproc_setin(conv, buf); - buf = abuf_new(nfr, aparams_bpf(&ipar)); + buf = abuf_new(nfr, &ipar); aproc_setout(conv, buf); ibufsz += nfr; } @@ -178,14 +178,14 @@ dev_init(char *devpath, * create the write end */ dev_play = wpipe_new(dev_file); - buf = abuf_new(nfr, aparams_bpf(dopar)); + buf = abuf_new(nfr, dopar); aproc_setin(dev_play, buf); obufsz += nfr; /* * append a converter, if needed */ - if (!aparams_eq(&opar, dopar)) { + if (!aparams_eqenc(&opar, dopar)) { if (debug_level > 0) { fprintf(stderr, "%s: ", devpath); aparams_print2(&opar, dopar); @@ -193,7 +193,7 @@ dev_init(char *devpath, } conv = conv_new("mixconv", &opar, dopar); aproc_setout(conv, buf); - buf = abuf_new(nfr, aparams_bpf(&opar)); + buf = abuf_new(nfr, &opar); aproc_setin(conv, buf); obufsz += nfr; } @@ -382,7 +382,9 @@ dev_attach(char *name, if (ibuf) { pbuf = LIST_FIRST(&dev_mix->obuflist); - if (!aparams_eq(ipar, &dev_opar)) { + if (!aparams_eqenc(ipar, &dev_opar) || + !aparams_eqrate(ipar, &dev_opar) || + !aparams_subset(ipar, &dev_opar)) { if (debug_level > 1) { fprintf(stderr, "dev_attach: %s: ", name); aparams_print2(ipar, &dev_opar); @@ -392,7 +394,7 @@ dev_attach(char *name, nfr -= nfr % dev_round; conv = conv_new(name, ipar, &dev_opar); aproc_setin(conv, ibuf); - ibuf = abuf_new(nfr, aparams_bpf(&dev_opar)); + ibuf = abuf_new(nfr, &dev_opar); aproc_setout(conv, ibuf); /* XXX: call abuf_fill() here ? */ } @@ -402,7 +404,9 @@ dev_attach(char *name, } if (obuf) { rbuf = LIST_FIRST(&dev_sub->ibuflist); - if (!aparams_eq(opar, &dev_ipar)) { + if (!aparams_eqenc(opar, &dev_ipar) || + !aparams_eqrate(opar, &dev_ipar) || + !aparams_subset(opar, &dev_ipar)) { if (debug_level > 1) { fprintf(stderr, "dev_attach: %s: ", name); aparams_print2(&dev_ipar, opar); @@ -412,7 +416,7 @@ dev_attach(char *name, nfr -= nfr % dev_round; conv = conv_new(name, &dev_ipar, opar); aproc_setout(conv, obuf); - obuf = abuf_new(nfr, aparams_bpf(&dev_ipar)); + obuf = abuf_new(nfr, &dev_ipar); aproc_setin(conv, obuf); } aproc_setout(dev_sub, obuf); diff --git a/usr.bin/aucat/sock.c b/usr.bin/aucat/sock.c index 7c9aecce3ea..76b3f3764a9 100644 --- a/usr.bin/aucat/sock.c +++ b/usr.bin/aucat/sock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sock.c,v 1.1 2008/10/26 08:49:44 ratchov Exp $ */ +/* $OpenBSD: sock.c,v 1.2 2008/11/03 22:25:13 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -324,13 +324,13 @@ sock_allocbuf(struct sock *f) if (f->mode & AMSG_PLAY) { nfr = f->bufsz - dev_bufsz * f->rpar.rate / dev_rate; - rbuf = abuf_new(nfr, aparams_bpf(&f->rpar)); + rbuf = abuf_new(nfr, &f->rpar); aproc_setout(f->pipe.file.rproc, rbuf); f->odelta = 0; } if (f->mode & AMSG_REC) { nfr = f->bufsz - dev_bufsz * f->wpar.rate / dev_rate; - wbuf = abuf_new(nfr, aparams_bpf(&f->wpar)); + wbuf = abuf_new(nfr, &f->wpar); aproc_setin(f->pipe.file.wproc, wbuf); f->idelta = 0; } |