On Wed, 11 May 2011 03:35:56 +0000
Jacob Meuser <jake...@sdf.lonestar.org> wrote:

> clipping is better than normalizing?  really?

Clipping might describe something like value&0xffffff, so no, not
clipping, saturating addition.
Try it and see for yourself.

> 
> what about the case where aucat is used for offline mixing?
> 

What about it?

> 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).
> 

I'm not taking anything away, I'm setting things right.
Like I already said, the -v option stays fully functional.
Everything can be boiled down to opinion. Please don't answer
in the style "you're wrong because I said so".
I've already given enough insight and evidence as to per why the
way it's done currently is wrong.
Explain why it's not important to adhere to the least surprise
principle.
Explain why is it better to force the users to choose between
two evils when they could be offered one good.
Explain why aucat should not model real world sound physics.

> 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.h  21 Oct 2010 18:57:42 -0000      1.23
> > +++ abuf.h  10 May 2011 22:58:18 -0000
> > @@ -46,7 +46,6 @@
> >     union {
> >             struct {
> >                     int weight;     /* dynamic range */     
> > -                   int maxweight;  /* max dynamic range allowed */
> >                     unsigned vol;   /* volume within the dynamic range */
> >                     unsigned done;  /* frames ready */
> >                     unsigned xrun;  /* 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.h       5 Nov 2010 16:42:17 -0000       1.11
> > +++ aparams.h       10 May 2011 22:58:18 -0000
> > @@ -19,6 +19,8 @@
> >  
> >  #include <sys/param.h>
> >  
> > +#include <limits.h>
> > +
> >  #define NCHAN_MAX  16              /* max channel in a stream */
> >  #define RATE_MIN   4000            /* min sample rate */
> >  #define RATE_MAX   192000          /* max sample rate */
> > @@ -64,6 +66,9 @@
> >  
> >  typedef short adata_t;
> >  
> > +#define ADATA_MIN          SHRT_MIN
> > +#define ADATA_MAX          SHRT_MAX
> > +
> >  #define ADATA_MUL(x,y)             (((int)(x) * (int)(y)) >> (ADATA_BITS - 
> > 1))
> >  #define ADATA_MULDIV(x,y,z)        ((int)(x) * (int)(y) / (int)(z))
> >  
> > @@ -71,6 +76,9 @@
> >  
> >  typedef int adata_t;
> >  
> > +#define ADATA_MIN          (-0xffffff / 2)
> > +#define ADATA_MAX          (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
> > +   register int sum;
> > +#else
> > +   register long long sum;
> > +#endif
> > +
> > +   sum = x;
> > +   sum += y;
> > +
> > +   if (sum < ADATA_MIN)
> > +           sum = ADATA_MIN;
> > +   else if (sum > ADATA_MAX)
> > +           sum = ADATA_MAX;
> > +
> > +   return (adata_t) sum;
> > +}
> > +#define ADATA_SADD(x,y)            adata_sadd(x,y)
> >  
> >  #define MIDI_MAXCTL                127
> >  #define MIDI_TO_ADATA(m)   (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.c 28 Apr 2011 07:20:03 -0000      1.64
> > +++ aproc.c 10 May 2011 22:58:19 -0000
> > @@ -617,6 +617,7 @@
> >     unsigned i, j, cc, istart, inext, onext, ostart;
> >     unsigned scount, icount, ocount;
> >     int vol;
> > +   adata_t sample;
> >  
> >  #ifdef DEBUG
> >     if (debug_level >= 4) {
> > @@ -673,7 +674,8 @@
> >     idata += istart;
> >     for (i = scount; i > 0; i--) {
> >             for (j = cc; j > 0; j--) {
> > -                   *odata += ADATA_MUL(*idata, vol);
> > +                   sample = ADATA_MUL(*idata, vol);
> > +                   *odata = ADATA_SADD(*odata, sample);
> >                     idata++;
> >                     odata++;
> >             }
> > @@ -914,8 +916,6 @@
> >     struct abuf *i, *obuf = LIST_FIRST(&p->outs);
> >     unsigned odone;
> >  
> > -   mix_setmaster(p);
> > -
> >     if (!aproc_inuse(p)) {
> >  #ifdef DEBUG
> >             if (debug_level >= 3) {
> > @@ -962,7 +962,6 @@
> >     ibuf->r.mix.done = 0;
> >     ibuf->r.mix.vol = ADATA_UNIT;
> >     ibuf->r.mix.weight = ADATA_UNIT;
> > -   ibuf->r.mix.maxweight = ADATA_UNIT;
> >     ibuf->r.mix.xrun = XRUN_IGNORE;
> >     ibuf->r.mix.drop = 0;
> >  }
> > @@ -1028,57 +1027,6 @@
> >     p->u.mix.ctl = NULL;
> >     p->u.mix.mon = NULL;
> >     return p;
> > -}
> > -
> > -/*
> > - * Normalize input levels.
> > - */
> > -void
> > -mix_setmaster(struct aproc *p)
> > -{
> > -   unsigned n;
> > -   struct abuf *i, *j;
> > -   int weight;
> > -
> > -   /*
> > -    * count the number of inputs. If a set of inputs
> > -    * uses channels that have no intersection, they are 
> > -    * counted only once because they don't need to 
> > -    * share their volume
> > -    *
> > -    * XXX: this is wrong, this is not optimal if we have two
> > -    *      buckets of N and N' clients, in which case we should
> > -    *      get 1/N and 1/N' respectively
> > -    */
> > -   n = 0;
> > -   LIST_FOREACH(i, &p->ins, ient) {
> > -           j = LIST_NEXT(i, ient);
> > -           for (;;) {
> > -                   if (j == NULL) {
> > -                           n++;
> > -                           break;
> > -                   }
> > -                   if (i->cmin > j->cmax || i->cmax < j->cmin)
> > -                           break;
> > -                   j = LIST_NEXT(j, ient);
> > -           }
> > -   }
> > -   LIST_FOREACH(i, &p->ins, ient) {
> > -           weight = ADATA_UNIT / n;
> > -           if (weight > i->r.mix.maxweight)
> > -                   weight = i->r.mix.maxweight;
> > -           i->r.mix.weight = weight;
> > -#ifdef DEBUG
> > -           if (debug_level >= 3) {
> > -                   abuf_dbg(i);
> > -                   dbg_puts(": setmaster: ");
> > -                   dbg_puti(i->r.mix.weight);
> > -                   dbg_puts("/");
> > -                   dbg_puti(i->r.mix.maxweight);
> > -                   dbg_puts("\n");
> > -           }
> > -#endif
> > -   }
> >  }
> >  
> >  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.c   21 Oct 2010 18:57:42 -0000      1.64
> > +++ dev.c   10 May 2011 22:58:19 -0000
> > @@ -998,8 +998,7 @@
> >             }
> >             aproc_setin(d->mix, ibuf);
> >             ibuf->r.mix.xrun = xrun;
> > -           ibuf->r.mix.maxweight = vol;
> > -           mix_setmaster(d->mix);
> > +           ibuf->r.mix.weight = vol;
> >     }
> >     if (mode & MODE_REC) {
> >             opar = *sopar;
> 
> -- 
> jake...@sdf.lonestar.org
> SDF Public Access UNIX System - http://sdf.lonestar.org

Reply via email to