freebsd-ports/audio/mpg123/files/patch-ad
Maxim Sobolev 40c0df04d2 Provide workaround for a bug in pcm driver introduced with format emulation
changes.

At present newpcm has sticky parameter settings, even when an
inappropriate value is set.  For instance, set format to alaw on h/w
that does not support alaw; newpcm interface state records format as
alaw, and subsequent unrelated state changes may fail, ie a rate change.

In mpg123 this can cause files to be played at lower quality
than available because of mis-diagnosis of available formats and
sample rates.  E.g downsamples everything to 11025Hz on this h/w as
12kHz probing breaks state and subsequent probes for higher supported
sampling rates.

PR:		25046
Submitted by:	Orion Hodson <oh@btinternet.com>
2001-02-13 15:00:44 +00:00

98 lines
2.2 KiB
Plaintext

--- audio_oss.c.orig Mon Feb 12 21:51:27 2001
+++ audio_oss.c Mon Feb 12 22:12:27 2001
@@ -143,12 +143,21 @@
int audio_set_channels(struct audio_info_struct *ai)
{
- int chan = ai->channels - 1;
+ int chan = ai->channels - 1, avail;
int ret;
if(ai->channels < 0)
return 0;
+ if (ioctl(ai->fn, SNDCTL_DSP_GETFMTS, &avail) < 0) {
+ perror("SNDCTL_DSP_GETFMTS");
+ return -1;
+ }
+
+ if (chan && (avail & AFMT_STEREO) == 0) {
+ return -1;
+ }
+
ret = ioctl(ai->fn, SNDCTL_DSP_STEREO, &chan);
if(chan != (ai->channels-1)) {
return -1;
@@ -158,8 +167,8 @@
int audio_set_format(struct audio_info_struct *ai)
{
- int sample_size,fmts;
- int sf,ret;
+ int sample_size, fmts, avail;
+ int sf;
if(ai->format == -1)
return 0;
@@ -194,17 +203,33 @@
if(ioctl(ai->fn, SNDCTL_DSP_SAMPLESIZE,&sample_size) < 0)
return -1;
#endif
+
+ /* newpcm note: need to check format is available before setting,
+ * otherwise driver will not successfully change speed or channels
+ * as format maybe incorrectly set in driver. newpcm probably needs
+ * modifying to stop broken formats sticking. */
+ if (ioctl(ai->fn, SNDCTL_DSP_GETFMTS, &avail) < 0) {
+ perror("SNDCTL_DSP_GETFMTS");
+ return -1;
+ }
+
+ if ((fmts & avail) == 0) {
+ return -1;
+ }
+
sf = fmts;
- ret = ioctl(ai->fn, SNDCTL_DSP_SETFMT, &fmts);
+ if (ioctl(ai->fn, SNDCTL_DSP_SETFMT, &fmts) < 0) {
+ perror("SNDCTL_DSP_SETFMT");
+ return -1;
+ }
if(sf != fmts) {
return -1;
}
- return ret;
+ return 0;
}
/*
- * get formats for specific channel/rate parameters
- */
+ * get formats for specific channel/rate parameters */
int audio_get_formats(struct audio_info_struct *ai)
{
int fmt = 0;
@@ -219,17 +244,17 @@
for(i=0;i<6;i++) {
ai->format = fmts[i];
- if(audio_set_format(ai) < 0) {
+ ai->rate = r;
+ if(audio_rate_best_match(ai) < 0) {
continue;
- }
+ }
ai->channels = c;
if(audio_set_channels(ai) < 0) {
continue;
}
- ai->rate = r;
- if(audio_rate_best_match(ai) < 0) {
+ if(audio_set_format(ai) < 0) {
continue;
- }
+ }
if( (ai->rate*100 > r*(100-AUDIO_RATE_TOLERANCE)) && (ai->rate*100 < r*(100+AUDIO_RATE_TOLERANCE)) ) {
fmt |= fmts[i];
}