tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Audio volume setting: not working - sometimes?

>>> The primary gain control might not be the one currently responsible
>>> for output volume depending on the various DACs available.
>> Possibly - but audioctl's play.gain field _does_ work to control the
>> output volume.  I had thought audioctl's play.gain was just a
>> different interface to the same thing [...]
> audioctl is primarily for manipulating /dev/sound, which persists
> these settings between opens, whereas /dev/audio doesn't. audioctl
> works by performing SETINFO on /dev/audioctl.

Right.  This has nothing to do with the issue at hand.  In the
problematic case, userland opens /dev/audio0 and tries to set the
playback gain (to 254).  This setting is ignored, according to both the
resulting signal and audioctl -a (run while the application still has
/dev/audio0 open).

> If you need the "audio device parameters persist between opens"
> feature I'd recommend using /dev/sound instead.

Persistence between opens is neither wanted nor relevant.

Today I had the leisure to track this down.  Building a kernel with
AUDIO_DEBUG and setting hw.audio0.debug to 2, I saw au_set_gain lines
indicating that the volume was getting changed as specified, only to be
immediately - as in, the next log line - changed back.

Turns out that, if you specify play.gain and play.balance in the same
AUDIO_SETINFO call, the former is ignored:

static int
audio_hw_setinfo(struct audio_softc *sc, const struct audio_info *newai,
	struct audio_info *oldai)
	u_int pgain;
	/* Backup play.{gain,balance} */
	if (SPECIFIED(newpi->gain) || SPECIFIED_CH(newpi->balance)) {
		au_get_gain(sc, &sc->sc_outports, &pgain, &pbalance);
		if (oldai) {
			oldpi->gain = pgain;
			oldpi->balance = pbalance;
	/* Backup record.{gain,balance} */
	if (SPECIFIED(newri->gain) || SPECIFIED_CH(newri->balance)) {
	if (SPECIFIED(newpi->gain)) {
		error = au_set_gain(sc, &sc->sc_outports,
		    newpi->gain, pbalance);
		if (error) {
	if (SPECIFIED(newri->gain)) {
	if (SPECIFIED_CH(newpi->balance)) {
		error = au_set_gain(sc, &sc->sc_outports,
		    pgain, newpi->balance);

Note that pgain is not changed between the "Backup play.{gain,balance}"
code and the last au_set_gain above, even if newpi->gain is specified.

Changing userland to call AUDIO_SETINFO twice, once with balance
specified and once with gain specified, is a workaround for my

PR filed - kern/56308.

/~\ The ASCII				  Mouse
\ / Ribbon Campaign
 X  Against HTML
/ \ Email!	     7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B

Home | Main Index | Thread Index | Old Index