On Tue May 10 2011 11:35:56 PM EDT, Jacob Meuser <jake...@sdf.lonestar.org> wrote:
> clipping is better than normalizing?B really? > > what about the case where aucat is used for offline mixing? > > like the mixerctl change, you are taking away things that exist > for good reason, because it makes *your* situation better in *your* > opinion, when you can (mostly) have what you want with the current > code (if you just try a little). > > On Wed, May 11, 2011 at 02:50:36AM +0300, Sviatoslav Chagaev wrote: > > I'm sitting at work, listening to music, debugging a web-application > > with JavaScript alert()s. Each time an alert window pops up, the > > browser plays a sound. For a brief moment, the volume drops twicefold > > then goes back to normal. This is annoying and doesn't make sense. > > > > In real life, if you are surrounded by multiple sound sources, their > > sound volumes will not be divided by the total amount of sound sources. > > Their sounds will add up until they blur and you can't distinguish > > anything anymore. Other operating systems, such as Macrohard Doors, do > > mixing by modeling this real world behaviour. > > > > In this sense, aucat violates the principle of least surprise. > > I'm used to how sound interacts in real world and then aucat steps in > > and introduces it's own laws of physics. > > > > To remedy this, aucat has an option -v, which lets you pre-divide the > > volume of inputs. This results in loss of dynamic range (quiet sounds > > might disappear and the maximum volume that you can set decreases). And > > also, if during usage the count of inputs raises above of what I > > predicted, the volume starts to jump up and down again. > > > > Experimentally, I've found that if you do a saturating addition between > > inputs, it sounds very much how it might have sounded in real world and > > how Macrohard Doors, among others, sounds like when playing > > multiple sounds. > > > > > > So, why is what I'm proposing better than what currently exists: > > > > * Resembles how sound behaves in real world more closely; > > * Doesn't violate the principle of least surprise; > > * No more annoying volume jumps up and down; > > * No need to use the -v option anymore / less stuff to remember / "it > > just works"; > > * No more choosing between being annoyed by volume jumps or loosing > > dynamic range. > > > > (This doesn't affect the -v option, it remains fully functional.) > > > > Tested on i386 and amd64 with 16 bits and 24 bits. > > > > > > Index: abuf.h > > =================================================================== > > RCS file: /OpenBSD/src/usr.bin/aucat/abuf.h,v > > retrieving revision 1.23 > > diff -u -r1.23 abuf.h > > --- abuf.hB B B 21 Oct 2010 18:57:42 -0000B B B 1.23 > > +++ abuf.hB B B 10 May 2011 22:58:18 -0000 > > @@ -46,7 +46,6 @@ > > B B B union { > > B B B B B B struct { > > B B B B B B B B B int weight;B B B /* dynamic range */B B B > > -B B B B B B B B B int maxweight;B B B /* max dynamic range allowed */ > > B B B B B B B B B unsigned vol;B B B /* volume within the dynamic range > > */ > > B B B B B B B B B unsigned done;B B B /* frames ready */ > > B B B B B B B B B unsigned xrun;B B B /* underrun policy */ > > Index: aparams.h > > =================================================================== > > RCS file: /OpenBSD/src/usr.bin/aucat/aparams.h,v > > retrieving revision 1.11 > > diff -u -r1.11 aparams.h > > --- aparams.hB B B 5 Nov 2010 16:42:17 -0000B B B 1.11 > > +++ aparams.hB B B 10 May 2011 22:58:18 -0000 > > @@ -19,6 +19,8 @@ > > > > #include <sys/param.h> > > > > +#include <limits.h> > > + > > #define NCHAN_MAXB B B 16B B B B B B /* max channel in a stream */ > > #define RATE_MINB B B 4000B B B B B B /* min sample rate */ > > #define RATE_MAXB B B 192000B B B B B B /* max sample rate */ > > @@ -64,6 +66,9 @@ > > > > typedef short adata_t; > > > > +#define ADATA_MINB B B B B B SHRT_MIN > > +#define ADATA_MAXB B B B B B SHRT_MAX > > + > > #define ADATA_MUL(x,y)B B B B B B (((int)(x) * (int)(y)) >> (ADATA_BITS - > > 1)) > > #define ADATA_MULDIV(x,y,z)B B B ((int)(x) * (int)(y) / (int)(z)) > > > > @@ -71,6 +76,9 @@ > > > > typedef int adata_t; > > > > +#define ADATA_MINB B B B B B (-0xffffff / 2) > > +#define ADATA_MAXB B B B B B (0xffffff / 2) > > + > > #if defined(__i386__) && defined(__GNUC__) > > > > static inline int > > @@ -119,6 +127,28 @@ > > #else > > #error "only 16-bit and 24-bit precisions are supported" > > #endif > > + > > +/* saturating addition */ > > +static inline adata_t > > +adata_sadd(register adata_t x, register adata_t y) > > +{ > > +#if ADATA_BITS <= 16 > > +B B B register int sum; > > +#else > > +B B B register long long sum; > > +#endif > > + > > +B B B sum = x; > > +B B B sum += y; > > + > > +B B B if (sum < ADATA_MIN) > > +B B B B B B sum = ADATA_MIN; > > +B B B else if (sum > ADATA_MAX) > > +B B B B B B sum = ADATA_MAX; > > + > > +B B B return (adata_t) sum; > > +} > > +#define ADATA_SADD(x,y)B B B B B B adata_sadd(x,y) > > > > #define MIDI_MAXCTLB B B B B B 127 > > #define MIDI_TO_ADATA(m)B B B (aparams_ctltovol[m] << (ADATA_BITS - 16)) > > Index: aproc.c > > =================================================================== > > RCS file: /OpenBSD/src/usr.bin/aucat/aproc.c,v > > retrieving revision 1.64 > > diff -u -r1.64 aproc.c > > --- aproc.cB B B 28 Apr 2011 07:20:03 -0000B B B 1.64 > > +++ aproc.cB B B 10 May 2011 22:58:19 -0000 > > @@ -617,6 +617,7 @@ > > B B B unsigned i, j, cc, istart, inext, onext, ostart; > > B B B unsigned scount, icount, ocount; > > B B B int vol; > > +B B B adata_t sample; > > > > #ifdef DEBUG > > B B B if (debug_level >= 4) { > > @@ -673,7 +674,8 @@ > > B B B idata += istart; > > B B B for (i = scount; i > 0; i--) { > > B B B B B B for (j = cc; j > 0; j--) { > > -B B B B B B B B B *odata += ADATA_MUL(*idata, vol); > > +B B B B B B B B B sample = ADATA_MUL(*idata, vol); > > +B B B B B B B B B *odata = ADATA_SADD(*odata, sample); > > B B B B B B B B B idata++; > > B B B B B B B B B odata++; > > B B B B B B } > > @@ -914,8 +916,6 @@ > > B B B struct abuf *i, *obuf = LIST_FIRST(&p->outs); > > B B B unsigned odone; > > > > -B B B mix_setmaster(p); > > - > > B B B if (!aproc_inuse(p)) { > > #ifdef DEBUG > > B B B B B B if (debug_level >= 3) { > > @@ -962,7 +962,6 @@ > > B B B ibuf->r.mix.done = 0; > > B B B ibuf->r.mix.vol = ADATA_UNIT; > > B B B ibuf->r.mix.weight = ADATA_UNIT; > > -B B B ibuf->r.mix.maxweight = ADATA_UNIT; > > B B B ibuf->r.mix.xrun = XRUN_IGNORE; > > B B B ibuf->r.mix.drop = 0; > > } > > @@ -1028,57 +1027,6 @@ > > B B B p->u.mix.ctl = NULL; > > B B B p->u.mix.mon = NULL; > > B B B return p; > > -} > > - > > -/* > > - * Normalize input levels. > > - */ > > -void > > -mix_setmaster(struct aproc *p) > > -{ > > -B B B unsigned n; > > -B B B struct abuf *i, *j; > > -B B B int weight; > > - > > -B B B /* > > -B B B * count the number of inputs. If a set of inputs > > -B B B * uses channels that have no intersection, they are > > -B B B * counted only once because they don't need to > > -B B B * share their volume > > -B B B * > > -B B B * XXX: this is wrong, this is not optimal if we have two > > -B B B *B B B B B buckets of N and N' clients, in which case we > > should > > -B B B *B B B get 1/N and 1/N' respectively > > -B B B */ > > -B B B n = 0; > > -B B B LIST_FOREACH(i, &p->ins, ient) { > > -B B B B B B j = LIST_NEXT(i, ient); > > -B B B B B B for (;;) { > > -B B B B B B B B B if (j == NULL) { > > -B B B B B B B B B B B B n++; > > -B B B B B B B B B B B B break; > > -B B B B B B B B B } > > -B B B B B B B B B if (i->cmin > j->cmax || i->cmax < j->cmin) > > -B B B B B B B B B B B B break; > > -B B B B B B B B B j = LIST_NEXT(j, ient); > > -B B B B B B } > > -B B B } > > -B B B LIST_FOREACH(i, &p->ins, ient) { > > -B B B B B B weight = ADATA_UNIT / n; > > -B B B B B B if (weight > i->r.mix.maxweight) > > -B B B B B B B B B weight = i->r.mix.maxweight; > > -B B B B B B i->r.mix.weight = weight; > > -#ifdef DEBUG > > -B B B B B B if (debug_level >= 3) { > > -B B B B B B B B B abuf_dbg(i); > > -B B B B B B B B B dbg_puts(": setmaster: "); > > -B B B B B B B B B dbg_puti(i->r.mix.weight); > > -B B B B B B B B B dbg_puts("/"); > > -B B B B B B B B B dbg_puti(i->r.mix.maxweight); > > -B B B B B B B B B dbg_puts("\n"); > > -B B B B B B } > > -#endif > > -B B B } > > } > > > > void > > Index: dev.c > > =================================================================== > > RCS file: /OpenBSD/src/usr.bin/aucat/dev.c,v > > retrieving revision 1.64 > > diff -u -r1.64 dev.c > > --- dev.cB B B 21 Oct 2010 18:57:42 -0000B B B 1.64 > > +++ dev.cB B B 10 May 2011 22:58:19 -0000 > > @@ -998,8 +998,7 @@ > > B B B B B B } > > B B B B B B aproc_setin(d->mix, ibuf); > > B B B B B B ibuf->r.mix.xrun = xrun; > > -B B B B B B ibuf->r.mix.maxweight = vol; > > -B B B B B B mix_setmaster(d->mix); > > +B B B B B B ibuf->r.mix.weight = vol; > > B B B } > > B B B if (mode & MODE_REC) { > > B B B B B B opar = *sopar; > > -- > jake...@sdf.lonestar.org > SDF Public Access UNIX System - http://sdf.lonestar.org > > > -- > This message has been scanned for viruses and > dangerous content by MailScanner, and is > believed to be clean. > -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.