summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorAlexandre Ratchov <ratchov@cvs.openbsd.org>2008-11-03 22:25:14 +0000
committerAlexandre Ratchov <ratchov@cvs.openbsd.org>2008-11-03 22:25:14 +0000
commit723c50cd1bb9337248bbd2997f9df971990edea2 (patch)
tree3c94418e6656ca04915ff70d6c17fc7f6d4aa12e /usr.bin
parent4aa23092c2f9e39b46581c898a9fd591b6c8a754 (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.c10
-rw-r--r--usr.bin/aucat/abuf.h12
-rw-r--r--usr.bin/aucat/aparams.c45
-rw-r--r--usr.bin/aucat/aparams.h5
-rw-r--r--usr.bin/aucat/aproc.c72
-rw-r--r--usr.bin/aucat/aucat.c6
-rw-r--r--usr.bin/aucat/dev.c26
-rw-r--r--usr.bin/aucat/sock.c6
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;
}