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
>Organization:
	Dis-
>Environment:
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
>Description:
	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).

>How-To-Repeat:
	Try it.  In my case, this looked like

	 AUDIO_INITINFO(&ai);
	 ai.play.sample_rate = 8000;
	 ai.play.channels = 1;
	 ai.play.precision = 16;
	 ai.play.encoding = AUDIO_ENCODING_ULINEAR_LE;
	 ai.play.gain = 254;
	 ai.play.port = oai.play.avail_ports;
	 ai.play.pause = 0;
	 ai.play.balance = AUDIO_MID_BALANCE;
	 ai.monitor_gain = 254;
	 ai.mode = AUMODE_PLAY | AUMODE_PLAY_ALL;
	 if (ioctl(fd,AUDIO_SETINFO,&ai) < 0)
	  { fprintf(stderr,"AUDIO_SETINFO: %s\n",strerror(errno));
	    exit(1);
	  }

	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.
>Fix:
	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		mouse%rodents-montreal.org@localhost
/ \ Email!	     7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B



Home | Main Index | Thread Index | Old Index