Subject: Re: Ideas on the audio framework
To: Luke Mewburn <lukem@NetBSD.org>
From: Robert Elz <kre@munnari.OZ.AU>
List: tech-kern
Date: 12/13/2004 15:04:42
    Date:        Mon, 13 Dec 2004 13:51:06 +1100
    From:        Luke Mewburn <lukem@NetBSD.org>
    Message-ID:  <20041213025106.GJ26258@mewburn.net>

  | On Sun, Dec 12, 2004 at 08:44:17PM -0600, Eric Haszlakiewicz wrote:
  |   | What else can you do with a volume knob?
  | 
  | Turn it up to 11.

That's actually a very insightful short message.

What matters is whether

	Turn it up to 11
	Turn it down to 11
	Set it to 11

all mean the same thing, or mean different things (that is, whether we
can expect the same results from all of them, or different ones).

I don't use audio on netbsd much (in general I like computers to be
quiet, and on one of mine, all the NetBSD sound driver ever produces
is appropriate lengths of silence, which is all it has ever done, for
years - which has never bothered me in the least...)

But, that said, my impression is that on NetBSD those 3 events don't
necessarily produce the same result, yet almost any normal user is
going to expect that they would (ie: it doesn't matter how the volume
gets to 11, 11 is 11, and should sound the same, for the same sound,
however the volume gets there).

I believe however, that if the hardware has volume steps 0 8 16 24 32 ...
and the volume is currently 8, then "turn it up to 11" results in the
volume being set to 16, which is the next louder value possible than 8.
On the other hand, if the volume is 16, then "turn it down to 11"
results in the volume being set to 8, which is the next quieter value
than existed before.

That is, we have twice set the volume to 11, and ended up with completely
different results, which is crazy as a human factor design (and that's
regardless of how you can justify it from "I needed to make X work" type
rationales - if this was the necessary result, then you didn't really
need to make X work at all).

But, and again, this is just what I think happens, if after the earlier
"turn it up to 11" we then do "turn it up to 13", what happens is that
the driver sees the volume go down from 16 to 13, which it has to
implement by setting it down to 8 (the next lower available step).
That means, I turn it up from 8 to 11, sound gets louder, I keep turning
up from 11 to 13, and now the sound gets quieter again.   Weird and
wacky - though easy to understand what's happening once the API is
explained (impossible to justify though).

[Aside: I think this is what the example someone gave of using "jot" to
pick values to hand to mixerctl (or whatever) was intended to illustrate.]

There are just two rational options here.   Either "set it to 11" has
to be an error, because the hardware can't actually do that - and so
applications have to discover the values that the hardware can actually
do, and generate requests only for those values (how that maps into the
GUI interface, or whatever, is irrelevant - that is, it is for the
application to decide) - any unsupported value would have to be an error
at the sys call interface.   Obviously there needs to be an API that the
application can use to discover the granularity of the interface.

Or, all values have to be made legal (within whatever is the appropriate
range) and mapped into hardware in such a way that bigger values always
mean louder in some fashion (even if the difference is actually 0, because
the hardware just doesn't have 256 different volume settings but the API
allows that many - if setting 10 and 11 and 12 all result in the same volume,
then so be it, provided going back 12 11 10 also retain the same settings -
if a push button "up" on the volume just increases by 1, over a range of 255,
the GUI is simply stupid/broken anyway - no-one wants to push a button 256
times to go from min to max, the GUI instead should simply decide to allow
16 volume settings, take the range of values from the API, divide by 16,
and increase the volume by range/16 every time the button is pushed, rather
than just by 1.

NetBSD does not need to support every broken application, what it does
need however is a rational and understandable API that works correctly.
Even better if that API is "stolen" from somewhere else.

And we most certainly should not have the kernel attempting to guess
what the application/user must have meant by what it did, and attempt
to make that happen, even though it means doing something different than
what the application actually requested taken literally.   If we must
have a "make it louder" API, which always makes a real measurable (if
perhaps inaudible) increase in the volume, then the API for it should
be exactly that: "make it louder" (or AUDIO_LOUDER as an ioctl command
or something like that).  Attempting to guess what the user really means
when the volume setting changes from 6 to 7 is simply wrong, and impossible.

kre