Backport from 1.3: most of the audio drivers can now handle data SDL-1.2
authorRyan C. Gordon <icculus@icculus.org>
Fri, 01 Sep 2006 22:50:24 +0000
branchSDL-1.2
changeset 3851 405a192b68e7
parent 3850 28db418c7573
child 3852 5b5e549382b3
Backport from 1.3: most of the audio drivers can now handle data conversion at a higher level when they can't open the hardware in the exact format requested.
src/audio/amigaos/SDL_ahiaudio.c
src/audio/baudio/SDL_beaudio.cc
src/audio/dart/SDL_dart.c
src/audio/dc/SDL_dcaudio.c
src/audio/dmedia/SDL_irixaudio.c
src/audio/mint/SDL_mintaudio_dma8.c
src/audio/mint/SDL_mintaudio_gsxb.c
src/audio/mint/SDL_mintaudio_mcsn.c
src/audio/mint/SDL_mintaudio_stfa.c
src/audio/mint/SDL_mintaudio_xbios.c
--- a/src/audio/amigaos/SDL_ahiaudio.c	Wed Aug 02 21:26:31 2006 +0000
+++ b/src/audio/amigaos/SDL_ahiaudio.c	Fri Sep 01 22:50:24 2006 +0000
@@ -220,47 +220,50 @@
 
 static int AHI_OpenAudio(_THIS, SDL_AudioSpec *spec)
 {	
-//	int width;
+    SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
+    int valid_datatype = 1;
 
-	D(bug("AHI opening...\n"));
-
-	/* Determine the audio parameters from the AudioSpec */
-	switch ( spec->format & 0xFF ) {
+    D(bug("AHI opening...\n"));
 
-		case 8: { /* Signed 8 bit audio data */
-			D(bug("Samples a 8 bit...\n"));
-			spec->format = AUDIO_S8;
-			this->hidden->bytespersample=1;
-			if(spec->channels<2)
-				this->hidden->type = AHIST_M8S;
-			else
-				this->hidden->type = AHIST_S8S;
-		}
-		break;
+    /* Determine the audio parameters from the AudioSpec */
+    while ((!valid_datatype) && (test_format)) {
+        valid_datatype = 1;
+        switch (test_format) {
+            case AUDIO_S8:
+                D(bug("AUDIO_S8...\n"));
+                spec->format = AUDIO_S8;
+                this->hidden->bytespersample = 1;
+                if (spec->channels < 2)
+                    this->hidden->type = AHIST_M8S;
+                else
+                    this->hidden->type = AHIST_S8S;
+                break;
 
-		case 16: { /* Signed 16 bit audio data */
-			D(bug("Samples a 16 bit...\n"));
-			spec->format = AUDIO_S16MSB;
-			this->hidden->bytespersample=2;
-			if(spec->channels<2)
-				this->hidden->type = AHIST_M16S;
-			else
-				this->hidden->type = AHIST_S16S;
-		}
-		break;
+            case AUDIO_S16MSB:
+                D(bug("AUDIO_S16MSB...\n"));
+                spec->format = AUDIO_S16MSB;
+                this->hidden->bytespersample = 2;
+                if (spec->channels < 2)
+                    this->hidden->type = AHIST_M16S;
+                else
+                    this->hidden->type = AHIST_S16S;
+                break;
 
-		default: {
-			SDL_SetError("Unsupported audio format");
-			return(-1);
-		}
-	}
+            default:
+                valid_datatype = 0;
+                test_format = SDL_NextAudioFormat();
+                break;
+        }
+    }
 
-	if(spec->channels!=1 && spec->channels!=2)
-	{
-		D(bug("Wrong channel number!\n"));
-		SDL_SetError("Channel number non supported");
-		return -1;
-	}
+    if (!valid_datatype) { /* shouldn't happen, but just in case... */
+        SDL_SetError("Unsupported audio format");
+        return (-1);
+    }
+
+    if (spec->channels > 2) {
+        spec->channels = 2;  /* will convert at higher level. */
+    }
 
 	D(bug("Before CalculateAudioSpec\n"));
 	/* Update the fragment size as size in bytes */
--- a/src/audio/baudio/SDL_beaudio.cc	Wed Aug 02 21:26:31 2006 +0000
+++ b/src/audio/baudio/SDL_beaudio.cc	Fri Sep 01 22:50:24 2006 +0000
@@ -152,38 +152,55 @@
 
 int BE_OpenAudio(_THIS, SDL_AudioSpec *spec)
 {
-	media_raw_audio_format format;
+    int valid_datatype = 0;
+    media_raw_audio_format format;
+    SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
 
-	/* Initialize the Be Application, if it's not already started */
-	if ( SDL_InitBeApp() < 0 ) {
-		return(-1);
-	}
+    /* Parse the audio format and fill the Be raw audio format */
+    memset(&format, '\0', sizeof (media_raw_audio_format));
+    format.byte_order = B_MEDIA_LITTLE_ENDIAN;
+    format.frame_rate = (float) spec->freq;
+    format.channel_count = spec->channels;  /* !!! FIXME: support > 2? */
+    while ((!valid_datatype) && (test_format)) {
+        valid_datatype = 1;
+        spec->format = test_format;
+        switch (test_format) {
+            case AUDIO_S8:
+                format.format = media_raw_audio_format::B_AUDIO_CHAR;
+                break;
+
+            case AUDIO_U8:
+                format.format = media_raw_audio_format::B_AUDIO_UCHAR;
+                break;
+
+            case AUDIO_S16LSB:
+                format.format = media_raw_audio_format::B_AUDIO_SHORT;
+                break;
 
-	/* Parse the audio format and fill the Be raw audio format */
-	format.frame_rate = (float)spec->freq;
-	format.channel_count = spec->channels;
-	switch (spec->format&~0x1000) {
-		case AUDIO_S8:
-			/* Signed 8-bit audio unsupported, convert to U8 */
-			spec->format = AUDIO_U8;
-		case AUDIO_U8:
-			format.format = media_raw_audio_format::B_AUDIO_UCHAR;
-			format.byte_order = 0;
-			break;
-		case AUDIO_U16:
-			/* Unsigned 16-bit audio unsupported, convert to S16 */
-			spec->format ^= 0x8000;
-		case AUDIO_S16:
-			format.format = media_raw_audio_format::B_AUDIO_SHORT;
-			if ( spec->format & 0x1000 ) {
-				format.byte_order = 1; /* Big endian */
-			} else {
-				format.byte_order = 2; /* Little endian */
-			}
-			break;
-	}
-	format.buffer_size = spec->samples;
-	
+            case AUDIO_S16MSB:
+                format.format = media_raw_audio_format::B_AUDIO_SHORT;
+                format.byte_order = B_MEDIA_BIG_ENDIAN;
+                break;
+
+            default:
+                valid_datatype = 0;
+                test_format = SDL_NextAudioFormat();
+                break;
+        }
+    }
+
+    if (!valid_datatype) { /* shouldn't happen, but just in case... */
+        SDL_SetError("Unsupported audio format");
+        return (-1);
+    }
+
+    /* Initialize the Be Application, if it's not already started */
+    if (SDL_InitBeApp() < 0) {
+        return (-1);
+    }
+
+    format.buffer_size = spec->samples;
+
 	/* Calculate the final parameters for this audio specification */
 	SDL_CalculateAudioSpec(spec);
 
--- a/src/audio/dart/SDL_dart.c	Wed Aug 02 21:26:31 2006 +0000
+++ b/src/audio/dart/SDL_dart.c	Fri Sep 01 22:50:24 2006 +0000
@@ -75,6 +75,8 @@
 
 int DART_OpenAudio(_THIS, SDL_AudioSpec *spec)
 {
+  SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
+  int valid_datatype = 0;
   MCI_AMP_OPEN_PARMS AmpOpenParms;
   MCI_GENERIC_PARMS GenericParms;
   int iDeviceOrd = 0; // Default device to be used
@@ -106,26 +108,39 @@
   iDeviceOrd = AmpOpenParms.usDeviceID;
 
   // Determine the audio parameters from the AudioSpec
-  switch ( spec->format & 0xFF )
-  {
-    case 8:
-        /* Unsigned 8 bit audio data */
-        spec->format = AUDIO_U8;
+  if (spec->channels > 2)
+    spec->channels = 2;  // !!! FIXME: more than stereo support in OS/2?
+
+  while ((!valid_datatype) && (test_format)) {
+    spec->format = test_format;
+    valid_datatype = 1;
+    switch (test_format) {
+      case AUDIO_U8:
+        // Unsigned 8 bit audio data
         iSilence = 0x80;
         iBits = 8;
         break;
-    case 16:
-        /* Signed 16 bit audio data */
-        spec->format = AUDIO_S16;
+
+      case AUDIO_S16LSB:
+        // Signed 16 bit audio data
         iSilence = 0x00;
         iBits = 16;
         break;
-    default:
-        // Close DART, and exit with error code!
-        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
-        SDL_SetError("Unsupported audio format");
-        return(-1);
+
+      default:
+        valid_datatype = 0;
+        test_format = SDL_NextAudioFormat();
+        break;
+    }
   }
+
+  if (!valid_datatype) { // shouldn't happen, but just in case...
+    // Close DART, and exit with error code!
+    mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
+    SDL_SetError("Unsupported audio format");
+    return (-1);
+  }
+
   iFreq = spec->freq;
   iChannels = spec->channels;
   /* Update the fragment size as size in bytes */
--- a/src/audio/dc/SDL_dcaudio.c	Wed Aug 02 21:26:31 2006 +0000
+++ b/src/audio/dc/SDL_dcaudio.c	Fri Sep 01 22:50:24 2006 +0000
@@ -201,13 +201,30 @@
 
 static int DCAUD_OpenAudio(_THIS, SDL_AudioSpec *spec)
 {
-	switch(spec->format&0xff) {
-	case  8: spec->format = AUDIO_S8; break;
-	case 16: spec->format = AUDIO_S16LSB; break;
-	default:
-		SDL_SetError("Unsupported audio format");
-		return(-1);
-	}
+    SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
+    int valid_datatype = 0;
+    while ((!valid_datatype) && (test_format)) {
+        spec->format = test_format;
+        switch (test_format) {
+            /* only formats Dreamcast accepts... */
+            case AUDIO_S8:
+            case AUDIO_S16LSB:
+                valid_datatype = 1;
+                break;
+
+            default:
+                test_format = SDL_NextAudioFormat();
+                break;
+        }
+    }
+
+    if (!valid_datatype) {  /* shouldn't happen, but just in case... */
+        SDL_SetError("Unsupported audio format");
+        return (-1);
+    }
+
+    if (spec->channels > 2)
+        spec->channels = 2;  /* no more than stereo on the Dreamcast. */
 
 	/* Update the fragment size as size in bytes */
 	SDL_CalculateAudioSpec(spec);
--- a/src/audio/dmedia/SDL_irixaudio.c	Wed Aug 02 21:26:31 2006 +0000
+++ b/src/audio/dmedia/SDL_irixaudio.c	Fri Sep 01 22:50:24 2006 +0000
@@ -139,78 +139,104 @@
 	}
 }
 
-static int AL_OpenAudio(_THIS, SDL_AudioSpec *spec)
+static int AL_OpenAudio(_THIS, SDL_AudioSpec * spec)
 {
-	ALconfig audio_config;
+	SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
+	long width = 0;
+	long fmt = 0;
+	int valid = 0;
+
 #ifdef OLD_IRIX_AUDIO
-	long audio_param[2];
+	{
+		long audio_param[2];
+		audio_param[0] = AL_OUTPUT_RATE;
+		audio_param[1] = spec->freq;
+		valid = (ALsetparams(AL_DEFAULT_DEVICE, audio_param, 2) < 0);
+	}
 #else
-	ALpv audio_param;
+	{
+		ALpv audio_param;
+		audio_param.param = AL_RATE;
+		audio_param.value.i = spec->freq;
+		valid = (alSetParams(AL_DEFAULT_OUTPUT, &audio_param, 1) < 0);
+	}
 #endif
-	int width;
+
+	while ((!valid) && (test_format)) {
+		valid = 1;
+		spec->format = test_format;
 
-	/* Determine the audio parameters from the AudioSpec */
-	switch ( spec->format & 0xFF ) {
+		switch (test_format) {
+			case AUDIO_S8:
+				width = AL_SAMPLE_8;
+				fmt = AL_SAMPFMT_TWOSCOMP;
+				break;
+
+			case AUDIO_S16SYS:
+				width = AL_SAMPLE_16;
+				fmt = AL_SAMPFMT_TWOSCOMP;
+				break;
 
-		case 8: { /* Signed 8 bit audio data */
-			spec->format = AUDIO_S8;
-			width = AL_SAMPLE_8;
+			default:
+				valid = 0;
+				test_format = SDL_NextAudioFormat();
+				break;
 		}
-		break;
+
+		if (valid) {
+			ALconfig audio_config = alNewConfig();
+			valid = 0;
+			if (audio_config) {
+				if (alSetChannels(audio_config, spec->channels) < 0) {
+					if (spec->channels > 2) {  /* can't handle > stereo? */
+						spec->channels = 2;  /* try again below. */
+					}
+				}
+
+				if ((alSetSampFmt(audio_config, fmt) >= 0) &&
+				    ((!width) || (alSetWidth(audio_config, width) >= 0)) &&
+				    (alSetQueueSize(audio_config, spec->samples * 2) >= 0) &&
+				    (alSetChannels(audio_config, spec->channels) >= 0)) {
 
-		case 16: { /* Signed 16 bit audio data */
-			spec->format = AUDIO_S16MSB;
-			width = AL_SAMPLE_16;
+					audio_port = alOpenPort("SDL audio", "w", audio_config);
+					if (audio_port == NULL) {
+						/* docs say AL_BAD_CHANNELS happens here, too. */
+						int err = oserror();
+						if (err == AL_BAD_CHANNELS) {
+							spec->channels = 2;
+							alSetChannels(audio_config, spec->channels);
+							audio_port = alOpenPort("SDL audio", "w",
+							                        audio_config);
+						}
+					}
+
+					if (audio_port != NULL) {
+						valid = 1;
+					}
+				}
+
+				alFreeConfig(audio_config);
+			}
 		}
-		break;
+	}
 
-		default: {
-			SDL_SetError("Unsupported audio format");
-			return(-1);
-		}
+	if (!valid) {
+		SDL_SetError("Unsupported audio format");
+		return (-1);
 	}
 
 	/* Update the fragment size as size in bytes */
 	SDL_CalculateAudioSpec(spec);
 
-	/* Set output frequency */
-#ifdef OLD_IRIX_AUDIO
-	audio_param[0] = AL_OUTPUT_RATE;
-	audio_param[1] = spec->freq;
-	if( ALsetparams(AL_DEFAULT_DEVICE, audio_param, 2) < 0 ) {
-#else
-	audio_param.param = AL_RATE;
-	audio_param.value.i = spec->freq;
-	if( alSetParams(AL_DEFAULT_OUTPUT, &audio_param, 1) < 0 ) {
-#endif
-		SDL_SetError("alSetParams failed");
-		return(-1);
-	}
-
-	/* Open the audio port with the requested frequency */
-	audio_port = NULL;
-	audio_config = alNewConfig();
-	if ( audio_config &&
-	     (alSetSampFmt(audio_config, AL_SAMPFMT_TWOSCOMP) >= 0) &&
-	     (alSetWidth(audio_config, width) >= 0) &&
-	     (alSetQueueSize(audio_config, spec->samples*2) >= 0) &&
-	     (alSetChannels(audio_config, spec->channels) >= 0) ) {
-		audio_port = alOpenPort("SDL audio", "w", audio_config);
-	}
-	alFreeConfig(audio_config);
-	if( audio_port == NULL ) {
-		SDL_SetError("Unable to open audio port");
-		return(-1);
-	}
-
 	/* Allocate mixing buffer */
-	mixbuf = (Uint8 *)SDL_AllocAudioMem(spec->size);
-	if ( mixbuf == NULL ) {
+	mixbuf = (Uint8 *) SDL_AllocAudioMem(spec->size);
+	if (mixbuf == NULL) {
 		SDL_OutOfMemory();
-		return(-1);
+		return (-1);
 	}
 	SDL_memset(mixbuf, spec->silence, spec->size);
 
 	/* We're ready to rock and roll. :-) */
-	return(0);
+	return (0);
 }
+
--- a/src/audio/mint/SDL_mintaudio_dma8.c	Wed Aug 02 21:26:31 2006 +0000
+++ b/src/audio/mint/SDL_mintaudio_dma8.c	Fri Sep 01 22:50:24 2006 +0000
@@ -217,6 +217,9 @@
 	DEBUG_PRINT(("channels=%d, ", spec->channels));
 	DEBUG_PRINT(("freq=%d\n", spec->freq));
 
+	if (spec->channels > 2)
+		spec->channels = 2;
+
 	/* Check formats available */
 	spec->format = AUDIO_S8;
 	
--- a/src/audio/mint/SDL_mintaudio_gsxb.c	Wed Aug 02 21:26:31 2006 +0000
+++ b/src/audio/mint/SDL_mintaudio_gsxb.c	Fri Sep 01 22:50:24 2006 +0000
@@ -201,6 +201,8 @@
 {
 	long snd_format;
 	int i, resolution, format_signed, format_bigendian;
+    SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
+    int valid_datatype = 0;
 
 	resolution = spec->format & 0x00ff;
 	format_signed = ((spec->format & 0x8000)!=0);
@@ -212,28 +214,46 @@
 	DEBUG_PRINT(("channels=%d, ", spec->channels));
 	DEBUG_PRINT(("freq=%d\n", spec->freq));
 
-	/* Check formats available */
-	snd_format = Sndstatus(SND_QUERYFORMATS);
-	switch (resolution) {
-		case 8:
-			if ((snd_format & SND_FORMAT8)==0) {
-				SDL_SetError("Mint_CheckAudio: 8 bits samples not supported");
-				return -1;
-			}
-			snd_format = Sndstatus(SND_QUERY8BIT);
-			break;
-		case 16:
-			if ((snd_format & SND_FORMAT16)==0) {
-				SDL_SetError("Mint_CheckAudio: 16 bits samples not supported");
-				return -1;
-			}
-			snd_format = Sndstatus(SND_QUERY16BIT);
-			break;
-		default:
-			SDL_SetError("Mint_CheckAudio: Unsupported sample resolution");
-			return -1;
-			break;
-	}
+    if (spec->channels > 2) {
+        spec->channels = 2;  /* no more than stereo! */
+    }
+
+    while ((!valid_datatype) && (test_format)) {
+        /* Check formats available */
+        snd_format = Sndstatus(SND_QUERYFORMATS);
+        spec->format = test_format;
+        resolution = SDL_AUDIO_BITSIZE(spec->format);
+        format_signed = SDL_AUDIO_ISSIGNED(spec->format);
+        format_bigendian = SDL_AUDIO_ISBIGENDIAN(spec->format);
+        switch (test_format) {
+            case AUDIO_U8:
+            case AUDIO_S8:
+                if (snd_format & SND_FORMAT8) {
+                    valid_datatype = 1;
+                    snd_format = Sndstatus(SND_QUERY8BIT);
+                }
+                break;
+
+            case AUDIO_U16LSB:
+            case AUDIO_S16LSB:
+            case AUDIO_U16MSB:
+            case AUDIO_S16MSB:
+                if (snd_format & SND_FORMAT16) {
+                    valid_datatype = 1;
+                    snd_format = Sndstatus(SND_QUERY16BIT);
+                }
+                break;
+
+            default:
+                test_format = SDL_NextAudioFormat();
+                break;
+        }
+    }
+
+    if (!valid_datatype) {
+        SDL_SetError("Unsupported audio format");
+        return (-1);
+    }
 
 	/* Check signed/unsigned format */
 	if (format_signed) {
--- a/src/audio/mint/SDL_mintaudio_mcsn.c	Wed Aug 02 21:26:31 2006 +0000
+++ b/src/audio/mint/SDL_mintaudio_mcsn.c	Fri Sep 01 22:50:24 2006 +0000
@@ -224,6 +224,10 @@
 	DEBUG_PRINT(("channels=%d, ", spec->channels));
 	DEBUG_PRINT(("freq=%d\n", spec->freq));
 
+    if (spec->channels > 2) {
+        spec->channels = 2;  /* no more than stereo! */
+    }
+
 	/* Check formats available */
 	MINTAUDIO_freqcount=0;
 	switch(cookie_mcsn->play) {
--- a/src/audio/mint/SDL_mintaudio_stfa.c	Wed Aug 02 21:26:31 2006 +0000
+++ b/src/audio/mint/SDL_mintaudio_stfa.c	Fri Sep 01 22:50:24 2006 +0000
@@ -205,6 +205,10 @@
 	DEBUG_PRINT(("channels=%d, ", spec->channels));
 	DEBUG_PRINT(("freq=%d\n", spec->freq));
 
+    if (spec->channels > 2) {
+        spec->channels = 2;  /* no more than stereo! */
+    }
+
 	/* Check formats available */
 	MINTAUDIO_freqcount=0;
 	for (i=0;i<16;i++) {
--- a/src/audio/mint/SDL_mintaudio_xbios.c	Wed Aug 02 21:26:31 2006 +0000
+++ b/src/audio/mint/SDL_mintaudio_xbios.c	Fri Sep 01 22:50:24 2006 +0000
@@ -341,6 +341,10 @@
 	DEBUG_PRINT(("channels=%d, ", spec->channels));
 	DEBUG_PRINT(("freq=%d\n", spec->freq));
 
+    if (spec->channels > 2) {
+        spec->channels = 2;  /* no more than stereo! */
+    }
+
 	spec->format |= 0x8000;	/* Audio is always signed */
 	if ((spec->format & 0x00ff)==16) {
 		spec->format |= 0x1000;	/* Audio is always big endian */