From df846417bb820037fcd0c33834a2667d8c94454a Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 1 Sep 2006 22:50:24 +0000 Subject: [PATCH] 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 | 85 +++++++++-------- src/audio/baudio/SDL_beaudio.cc | 79 +++++++++------- src/audio/dart/SDL_dart.c | 41 +++++--- src/audio/dc/SDL_dcaudio.c | 31 +++++-- src/audio/dmedia/SDL_irixaudio.c | 134 ++++++++++++++++----------- src/audio/mint/SDL_mintaudio_dma8.c | 3 + src/audio/mint/SDL_mintaudio_gsxb.c | 64 ++++++++----- src/audio/mint/SDL_mintaudio_mcsn.c | 4 + src/audio/mint/SDL_mintaudio_stfa.c | 4 + src/audio/mint/SDL_mintaudio_xbios.c | 4 + 10 files changed, 281 insertions(+), 168 deletions(-) diff --git a/src/audio/amigaos/SDL_ahiaudio.c b/src/audio/amigaos/SDL_ahiaudio.c index c9a4c1a4f..1db0f8457 100644 --- a/src/audio/amigaos/SDL_ahiaudio.c +++ b/src/audio/amigaos/SDL_ahiaudio.c @@ -220,47 +220,50 @@ static void AHI_CloseAudio(_THIS) static int AHI_OpenAudio(_THIS, SDL_AudioSpec *spec) { -// int width; - - D(bug("AHI opening...\n")); - - /* Determine the audio parameters from the AudioSpec */ - switch ( spec->format & 0xFF ) { - - 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; - - 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; - - default: { - SDL_SetError("Unsupported audio format"); - return(-1); - } - } - - if(spec->channels!=1 && spec->channels!=2) - { - D(bug("Wrong channel number!\n")); - SDL_SetError("Channel number non supported"); - return -1; - } + SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format); + int valid_datatype = 1; + + D(bug("AHI opening...\n")); + + /* 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 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: + 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); + } + + 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 */ diff --git a/src/audio/baudio/SDL_beaudio.cc b/src/audio/baudio/SDL_beaudio.cc index b074f9c2b..a88d09759 100644 --- a/src/audio/baudio/SDL_beaudio.cc +++ b/src/audio/baudio/SDL_beaudio.cc @@ -152,38 +152,55 @@ void BE_CloseAudio(_THIS) 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); + + /* 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; + + 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; - /* 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 */ - 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; - /* Calculate the final parameters for this audio specification */ SDL_CalculateAudioSpec(spec); diff --git a/src/audio/dart/SDL_dart.c b/src/audio/dart/SDL_dart.c index 6381de161..8cdf68aba 100644 --- a/src/audio/dart/SDL_dart.c +++ b/src/audio/dart/SDL_dart.c @@ -75,6 +75,8 @@ LONG APIENTRY DARTEventFunc(ULONG ulStatus, 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 @@ int DART_OpenAudio(_THIS, SDL_AudioSpec *spec) 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 */ diff --git a/src/audio/dc/SDL_dcaudio.c b/src/audio/dc/SDL_dcaudio.c index 8715376fa..7dc8410d0 100644 --- a/src/audio/dc/SDL_dcaudio.c +++ b/src/audio/dc/SDL_dcaudio.c @@ -201,13 +201,30 @@ static void DCAUD_CloseAudio(_THIS) 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); diff --git a/src/audio/dmedia/SDL_irixaudio.c b/src/audio/dmedia/SDL_irixaudio.c index 96cbaef67..37352ae55 100644 --- a/src/audio/dmedia/SDL_irixaudio.c +++ b/src/audio/dmedia/SDL_irixaudio.c @@ -139,78 +139,104 @@ static void AL_CloseAudio(_THIS) } } -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; - - /* Determine the audio parameters from the AudioSpec */ - switch ( spec->format & 0xFF ) { - case 8: { /* Signed 8 bit audio data */ - spec->format = AUDIO_S8; - width = AL_SAMPLE_8; + while ((!valid) && (test_format)) { + valid = 1; + spec->format = test_format; + + 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; + + default: + valid = 0; + test_format = SDL_NextAudioFormat(); + break; } - break; - case 16: { /* Signed 16 bit audio data */ - spec->format = AUDIO_S16MSB; - width = AL_SAMPLE_16; + 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)) { + + 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); } + diff --git a/src/audio/mint/SDL_mintaudio_dma8.c b/src/audio/mint/SDL_mintaudio_dma8.c index 39e7a6d22..b5e97039a 100644 --- a/src/audio/mint/SDL_mintaudio_dma8.c +++ b/src/audio/mint/SDL_mintaudio_dma8.c @@ -217,6 +217,9 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) 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; diff --git a/src/audio/mint/SDL_mintaudio_gsxb.c b/src/audio/mint/SDL_mintaudio_gsxb.c index de35debf5..742ff439e 100644 --- a/src/audio/mint/SDL_mintaudio_gsxb.c +++ b/src/audio/mint/SDL_mintaudio_gsxb.c @@ -201,6 +201,8 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) { 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 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) 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) { diff --git a/src/audio/mint/SDL_mintaudio_mcsn.c b/src/audio/mint/SDL_mintaudio_mcsn.c index 9741a3bea..cbaa6be5d 100644 --- a/src/audio/mint/SDL_mintaudio_mcsn.c +++ b/src/audio/mint/SDL_mintaudio_mcsn.c @@ -224,6 +224,10 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) 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) { diff --git a/src/audio/mint/SDL_mintaudio_stfa.c b/src/audio/mint/SDL_mintaudio_stfa.c index 552a7b224..80c76f7e0 100644 --- a/src/audio/mint/SDL_mintaudio_stfa.c +++ b/src/audio/mint/SDL_mintaudio_stfa.c @@ -205,6 +205,10 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) 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++) { diff --git a/src/audio/mint/SDL_mintaudio_xbios.c b/src/audio/mint/SDL_mintaudio_xbios.c index 016d4fa59..e1bfed7f9 100644 --- a/src/audio/mint/SDL_mintaudio_xbios.c +++ b/src/audio/mint/SDL_mintaudio_xbios.c @@ -341,6 +341,10 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) 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 */