NetBSD-Bugs archive

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

kern/56308: AUDIO_SETINFO can't set play.gain and play.balance together

>Number:         56308
>Category:       kern
>Synopsis:       AUDIO_SETINFO can't set play.gain and play.balance together
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Jul 13 19:30:00 +0000 2021
>Originator:     Mouse
>Release:        NetBSD 9.1
System: NetBSD Aaeon-9.Rodents-Montreal.ORG 9.1 NetBSD 9.1 (GEN91) #0: Fri Aug 13 14:35:31 EDT 2021  mouse%Aaeon-9.Rodents-Montreal.ORG@localhost:/home/mouse/kbuild/GEN91 amd64
Architecture: x86_64
Machine: amd64
	When using ioctl(...,AUDIO_SETINFO,...) with both play.gain and
	play.balance specified, the former is ignored.

	This is beacuse audio_hw_setinfo fails to update pgain if
	newpi->gain is specified:

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

	I find that calling AUDIO_SETINFO twice, once with balance but
	not gain specified and once with gain but not balance
	specified, works as a workaround (which is why I set priority
	to low).

	Try it.  In my case, this looked like

	 AUDIO_INITINFO(&ai); = 8000; = 1; = 16; = AUDIO_ENCODING_ULINEAR_LE; = 254; =; = 0; = AUDIO_MID_BALANCE;
	 ai.monitor_gain = 254;
	 if (ioctl(fd,AUDIO_SETINFO,&ai) < 0)
	  { fprintf(stderr,"AUDIO_SETINFO: %s\n",strerror(errno));

	with the volume formerly set to something other than 254.
	Verify, by listening to the audio or by checking with
	audioctl(1), that the volume is not actually changed.
	Presumably, the "if (SPECIFIED(newpi->gain))" block needs to
	set pgain to something.  I have not tried this; I have a
	workaround and I'd rather leave figuring out the correct thing
	to set pgain to to someone who knows this code.  (My guess
	would be

	pgain = newpi->gain

	but that is just a guess; I'm not as sure as I'd like that
	pgain and newpi->gain use compatible scales.)

	I suspect recording needs a similar fix, but I have not tried
	that; my use case doesn't record.

/~\ 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