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.

Reply via email to