diff --git a/aucat/aproc.c b/aucat/aproc.c index 00db513..de82a4f 100644 --- a/aucat/aproc.c +++ b/aucat/aproc.c @@ -1016,7 +1016,7 @@ struct aproc_ops mix_ops = { }; struct aproc * -mix_new(char *name, int maxlat, unsigned round) +mix_new(char *name, int maxlat, unsigned round, unsigned autovol) { struct aproc *p; @@ -1027,6 +1027,7 @@ mix_new(char *name, int maxlat, unsigned round) p->u.mix.maxlat = maxlat; p->u.mix.ctl = NULL; p->u.mix.mon = NULL; + p->u.mix.autovol = autovol; return p; } @@ -1040,6 +1041,9 @@ mix_setmaster(struct aproc *p) struct abuf *i, *j; int weight; + if (!p->u.mix.autovol) + return; + /* * count the number of inputs. If a set of inputs * uses channels that have no intersection, they are diff --git a/aucat/aproc.h b/aucat/aproc.h index 86c707a..a85a7d2 100644 --- a/aucat/aproc.h +++ b/aucat/aproc.h @@ -140,6 +140,7 @@ struct aproc { unsigned abspos; /* frames produced */ struct aproc *ctl; /* MIDI control/sync */ struct aproc *mon; /* snoop output */ + unsigned autovol; /* adjust volume dynamically */ } mix; struct { unsigned idle; /* frames since idleing */ @@ -239,7 +240,7 @@ 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, unsigned); +struct aproc *mix_new(char *, int, unsigned, unsigned); struct aproc *sub_new(char *, int, unsigned); struct aproc *resamp_new(char *, unsigned, unsigned); struct aproc *enc_new(char *, struct aparams *); diff --git a/aucat/aucat.1 b/aucat/aucat.1 index c45b3d2..7f7faa3 100644 --- a/aucat/aucat.1 +++ b/aucat/aucat.1 @@ -42,6 +42,7 @@ .Op Fl t Ar mode .Op Fl U Ar unit .Op Fl v Ar volume +.Op Fl w Ar flag .Op Fl x Ar policy .Op Fl z Ar nframes .Ek @@ -114,7 +115,7 @@ Preceding streams control MIDI ports .Pq Fl q , and per-device options -.Pq Fl abz +.Pq Fl abwz apply to this device. Device mode and parameters are determined from streams attached to it. @@ -255,6 +256,22 @@ of clients as long as their number is small enough. A good compromise is to use \-4dB attenuation (12 volume units) for each additional client expected (115 if 2 clients are expected, 103 for 3 clients, and so on). +.It Fl w Ar flag +Control whether the master volume resulting of all playback +streams of the device is automatically adjusted. +If the flag is +.Va on , +then the master volume is lowered when necessary to ensure +clipping never occurs. +It should be set to +.Va off +to avoid lowering the volume twice if streams are already pre-scaled. +Note that stream volumes can be manually set +.Pq Fl v +and if they are set correctly, the master volume doesn't need +to be adjusted to avoid clipping. +The default is +.Va on . .It Fl x Ar policy Action when the output stream cannot accept recorded data fast enough or the input stream @@ -298,7 +315,7 @@ to a 400 frame block size. .Pp On the command line, per-device parameters -.Pq Fl abz +.Pq Fl abwz must precede the device definition .Pq Fl f , and per-stream parameters diff --git a/aucat/aucat.c b/aucat/aucat.c index 1f52819..eef8290 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -251,6 +251,7 @@ struct cfdev { struct aparams ipar; /* input (read) parameters */ struct aparams opar; /* output (write) parameters */ unsigned hold; /* open immediately */ + unsigned autovol; /* adjust volumes */ unsigned bufsz; /* par.bufsz for sio device */ unsigned round; /* par.round for sio device */ unsigned mode; /* bitmap of MODE_XXX */ @@ -443,7 +444,7 @@ aucat_usage(void) "[-o file]\n\t" "[-q device] [-r rate] [-s name] [-t mode] [-U unit] " "[-v volume]\n\t" - "[-x policy] [-z nframes]\n", + "[-w flag] [-x policy] [-z nframes]\n", stderr); } @@ -512,8 +513,9 @@ aucat_main(int argc, char **argv) cd->bufsz = 0; cd->round = 0; cd->hold = 1; + cd->autovol = 1; - while ((c = getopt(argc, argv, "a:dnb:c:C:e:r:h:x:v:i:o:f:m:luq:s:U:L:t:j:z:")) != -1) { + while ((c = getopt(argc, argv, "a:w:dnb:c:C:e:r:h:x:v:i:o:f:m:luq:s:U:L:t:j:z:")) != -1) { switch (c) { case 'd': #ifdef DEBUG @@ -593,6 +595,9 @@ aucat_main(int argc, char **argv) case 'a': cd->hold = opt_onoff(); break; + case 'w': + cd->autovol = opt_onoff(); + break; case 'q': cfmid_add(&cd->mids, optarg); break; @@ -731,7 +736,7 @@ aucat_main(int argc, char **argv) } else { d = dev_new_sio(cd->path, cd->mode | MODE_MIDIMASK, &cd->ipar, &cd->opar, cd->bufsz, cd->round, - cd->hold); + cd->hold, cd->autovol); } if (d == NULL) errx(1, "%s: can't open device", cd->path); diff --git a/aucat/dev.c b/aucat/dev.c index 2c4cfce..fcf146a 100644 --- a/aucat/dev.c +++ b/aucat/dev.c @@ -114,7 +114,7 @@ struct dev *dev_list = NULL; struct dev * dev_new_sio(char *path, unsigned mode, struct aparams *dipar, struct aparams *dopar, - unsigned bufsz, unsigned round, unsigned hold) + unsigned bufsz, unsigned round, unsigned hold, unsigned autovol) { struct dev *d; @@ -132,6 +132,7 @@ dev_new_sio(char *path, d->reqbufsz = bufsz; d->reqround = round; d->hold = hold; + d->autovol = autovol; d->pstate = DEV_CLOSED; d->next = dev_list; dev_list = d; @@ -299,7 +300,7 @@ dev_open(struct dev *d) * Create mixer, demuxer and monitor */ if (d->mode & MODE_PLAY) { - d->mix = mix_new("play", d->bufsz, d->round); + d->mix = mix_new("play", d->bufsz, d->round, d->autovol); d->mix->refs++; d->mix->u.mix.ctl = d->midi; } diff --git a/aucat/dev.h b/aucat/dev.h index 58ad1bd..193a8dc 100644 --- a/aucat/dev.h +++ b/aucat/dev.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dev.h,v 1.27 2010/07/06 01:12:45 ratchov Exp $ */ +/* $OpenBSD$ */ /* * Copyright (c) 2008 Alexandre Ratchov * @@ -34,6 +34,7 @@ struct dev { unsigned reqround; /* block size */ unsigned reqrate; /* sample rate */ unsigned hold; /* hold the device open ? */ + unsigned autovol; /* auto adjust playvol ? */ unsigned refcnt; /* number of openers */ #define DEV_CLOSED 0 /* closed */ #define DEV_INIT 1 /* stopped */ @@ -64,7 +65,8 @@ void dev_drain(struct dev *); struct dev *dev_new_thru(void); struct dev *dev_new_loop(struct aparams *, struct aparams *, unsigned); struct dev *dev_new_sio(char *, unsigned, - struct aparams *, struct aparams *, unsigned, unsigned, unsigned); + struct aparams *, struct aparams *, + unsigned, unsigned, unsigned, unsigned); int dev_thruadd(struct dev *, char *, int, int); void dev_midiattach(struct dev *, struct abuf *, struct abuf *); unsigned dev_roundof(struct dev *, unsigned);