Bug 26563

Summary: ioctl(SNDCTL_DSP_SPEED) returns -1 when fall back to orignal sample rate
Product: Base System Reporter: huangant <huangant>
Component: kernAssignee: sound
Status: Closed FIXED    
Severity: Affects Only Me CC: huangant
Priority: Normal    
Version: 4.3-BETA2   
Hardware: Any   
OS: Any   

Description huangant 2001-04-14 08:30:01 UTC
	When I am trying to set output sample rate that my sound card
	not support (my sound card is fixed at 48khz), the
	ioctl(SNDCTL_DSP_SPEED) return -1 and the value passed into 
	ioctl() keep unchanged.
	
	According to OSS programming guide, the ioctl() should ONLY
	return -1 when critical/serious fault happens. When fails on
	setting sample rates, it should return 0 (no error) and
	change the value passed into ioctl() to the sample rate
	previous used.
	
	This problem will happen on some fixed sample rate sound chips,
	for example, VIA 82C686 AC'97 Codec, and cause some media player
	(such as 'xmms') caused an incorrect sound output.

	This problem exists in 4.3-BETA2, RC, and 20010412-CURRENT.

Fix: Here is a very sample patch to solve this problem.
	The patch is just return correct value when sample rate
	falling back to previous rate caused by setting unsupported
	sample rate.

	PS. This patch is generate based on 4.3-BETA2, but it has
	been tested on 4.3-RC(OK) and
	20010412-CURRENT(with some offset).

=== cut here ===


After applying this patch, result of above test code shows:
	
	trying setting 44100hz...[48000]
	
	on my VIA 82C686 AC'97 Codec.:)--CCUFcW6DTA6DchyE0AGr0mELoFPxf7yJHc2Iy6XrDJerZjgl
Content-Type: text/plain; name="file.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="file.diff"

--- sys/dev/sound/pcm/channel.c.old	Fri Apr 13 11:55:53 2001
+++ sys/dev/sound/pcm/channel.c	Fri Apr 13 11:56:14 2001
@@ -1178,7 +1178,7 @@
 	r = chn_tryspeed(c, speed);
 	if (r) {
 		DEB(printf("Failed to set speed %d falling back to %d\n", speed, oldspeed));
-		chn_tryspeed(c, oldspeed);
+		r = chn_tryspeed(c, oldspeed);
 	}
 	return r;
 }
=== cut here ===
How-To-Repeat: 
	Run following piece of the code:
=== cut here ===
#include <stdio.h>
#include <fcntl.h>
#include <sys/soundcard.h>

int main() {
	int fd, freq;
	
	if((fd = open("/dev/dsp", O_WRONLY))==-1) {
		printf("open %s failed.\n", "/dev/dsp");
		return(-1);
	}

	freq = 44100;
	printf("trying setting 44100hz...");
	if(ioctl(fd, SNDCTL_DSP_SPEED, &freq)==-1)
		freq = -1;
	printf("[%d]\n", freq);

	close(fd);
	return(0);
}
=== cut here ===

	When setting 44.1khz as sample rate, ioctl() will return -1 and
	keep freq==44100 on my VIA82C686 AC'97 Codec.

	Before applying any patches, result of this code shows:
	
	trying setting 44100hz...[-1]
Comment 1 iedowse freebsd_committer freebsd_triage 2002-12-01 03:29:21 UTC
Responsible Changed
From-To: freebsd-bugs->sound


Sound-related PR.
Comment 2 orion freebsd_committer freebsd_triage 2003-02-26 14:43:40 UTC
State Changed
From-To: open->closed

Applied, albeit very late after submission! 

With the feeder code these days do automatic rate and format 
conversion, this isn't a particular problem now. 

Thanks.