Commit 212dbcb7 authored by Ryan C. Gordon's avatar Ryan C. Gordon

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.

--HG--
branch : SDL-1.2
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/branches/SDL-1.2%402063
parent d5e84bbf
...@@ -220,46 +220,49 @@ static void AHI_CloseAudio(_THIS) ...@@ -220,46 +220,49 @@ static void AHI_CloseAudio(_THIS)
static int AHI_OpenAudio(_THIS, SDL_AudioSpec *spec) 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")); D(bug("AHI opening...\n"));
/* Determine the audio parameters from the AudioSpec */ /* Determine the audio parameters from the AudioSpec */
switch ( spec->format & 0xFF ) { while ((!valid_datatype) && (test_format)) {
valid_datatype = 1;
case 8: { /* Signed 8 bit audio data */ switch (test_format) {
D(bug("Samples a 8 bit...\n")); case AUDIO_S8:
D(bug("AUDIO_S8...\n"));
spec->format = AUDIO_S8; spec->format = AUDIO_S8;
this->hidden->bytespersample=1; this->hidden->bytespersample = 1;
if(spec->channels<2) if (spec->channels < 2)
this->hidden->type = AHIST_M8S; this->hidden->type = AHIST_M8S;
else else
this->hidden->type = AHIST_S8S; this->hidden->type = AHIST_S8S;
}
break; break;
case 16: { /* Signed 16 bit audio data */ case AUDIO_S16MSB:
D(bug("Samples a 16 bit...\n")); D(bug("AUDIO_S16MSB...\n"));
spec->format = AUDIO_S16MSB; spec->format = AUDIO_S16MSB;
this->hidden->bytespersample=2; this->hidden->bytespersample = 2;
if(spec->channels<2) if (spec->channels < 2)
this->hidden->type = AHIST_M16S; this->hidden->type = AHIST_M16S;
else else
this->hidden->type = AHIST_S16S; this->hidden->type = AHIST_S16S;
}
break; break;
default: { default:
SDL_SetError("Unsupported audio format"); valid_datatype = 0;
return(-1); test_format = SDL_NextAudioFormat();
break;
} }
} }
if(spec->channels!=1 && spec->channels!=2) if (!valid_datatype) { /* shouldn't happen, but just in case... */
{ SDL_SetError("Unsupported audio format");
D(bug("Wrong channel number!\n")); return (-1);
SDL_SetError("Channel number non supported"); }
return -1;
if (spec->channels > 2) {
spec->channels = 2; /* will convert at higher level. */
} }
D(bug("Before CalculateAudioSpec\n")); D(bug("Before CalculateAudioSpec\n"));
......
...@@ -152,36 +152,53 @@ void BE_CloseAudio(_THIS) ...@@ -152,36 +152,53 @@ void BE_CloseAudio(_THIS)
int BE_OpenAudio(_THIS, SDL_AudioSpec *spec) int BE_OpenAudio(_THIS, SDL_AudioSpec *spec)
{ {
int valid_datatype = 0;
media_raw_audio_format format; 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 */ /* Parse the audio format and fill the Be raw audio format */
format.frame_rate = (float)spec->freq; memset(&format, '\0', sizeof (media_raw_audio_format));
format.channel_count = spec->channels; format.byte_order = B_MEDIA_LITTLE_ENDIAN;
switch (spec->format&~0x1000) { 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: case AUDIO_S8:
/* Signed 8-bit audio unsupported, convert to U8 */ format.format = media_raw_audio_format::B_AUDIO_CHAR;
spec->format = AUDIO_U8; break;
case AUDIO_U8: case AUDIO_U8:
format.format = media_raw_audio_format::B_AUDIO_UCHAR; format.format = media_raw_audio_format::B_AUDIO_UCHAR;
format.byte_order = 0;
break; break;
case AUDIO_U16:
/* Unsigned 16-bit audio unsupported, convert to S16 */ case AUDIO_S16LSB:
spec->format ^= 0x8000;
case AUDIO_S16:
format.format = media_raw_audio_format::B_AUDIO_SHORT; 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; 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; format.buffer_size = spec->samples;
/* Calculate the final parameters for this audio specification */ /* Calculate the final parameters for this audio specification */
......
...@@ -75,6 +75,8 @@ LONG APIENTRY DARTEventFunc(ULONG ulStatus, ...@@ -75,6 +75,8 @@ LONG APIENTRY DARTEventFunc(ULONG ulStatus,
int DART_OpenAudio(_THIS, SDL_AudioSpec *spec) 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_AMP_OPEN_PARMS AmpOpenParms;
MCI_GENERIC_PARMS GenericParms; MCI_GENERIC_PARMS GenericParms;
int iDeviceOrd = 0; // Default device to be used int iDeviceOrd = 0; // Default device to be used
...@@ -106,26 +108,39 @@ int DART_OpenAudio(_THIS, SDL_AudioSpec *spec) ...@@ -106,26 +108,39 @@ int DART_OpenAudio(_THIS, SDL_AudioSpec *spec)
iDeviceOrd = AmpOpenParms.usDeviceID; iDeviceOrd = AmpOpenParms.usDeviceID;
// Determine the audio parameters from the AudioSpec // Determine the audio parameters from the AudioSpec
switch ( spec->format & 0xFF ) if (spec->channels > 2)
{ spec->channels = 2; // !!! FIXME: more than stereo support in OS/2?
case 8:
/* Unsigned 8 bit audio data */ while ((!valid_datatype) && (test_format)) {
spec->format = AUDIO_U8; spec->format = test_format;
valid_datatype = 1;
switch (test_format) {
case AUDIO_U8:
// Unsigned 8 bit audio data
iSilence = 0x80; iSilence = 0x80;
iBits = 8; iBits = 8;
break; break;
case 16:
/* Signed 16 bit audio data */ case AUDIO_S16LSB:
spec->format = AUDIO_S16; // Signed 16 bit audio data
iSilence = 0x00; iSilence = 0x00;
iBits = 16; iBits = 16;
break; break;
default: 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! // Close DART, and exit with error code!
mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
SDL_SetError("Unsupported audio format"); SDL_SetError("Unsupported audio format");
return(-1); return (-1);
} }
iFreq = spec->freq; iFreq = spec->freq;
iChannels = spec->channels; iChannels = spec->channels;
/* Update the fragment size as size in bytes */ /* Update the fragment size as size in bytes */
......
...@@ -201,14 +201,31 @@ static void DCAUD_CloseAudio(_THIS) ...@@ -201,14 +201,31 @@ static void DCAUD_CloseAudio(_THIS)
static int DCAUD_OpenAudio(_THIS, SDL_AudioSpec *spec) static int DCAUD_OpenAudio(_THIS, SDL_AudioSpec *spec)
{ {
switch(spec->format&0xff) { SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
case 8: spec->format = AUDIO_S8; break; int valid_datatype = 0;
case 16: spec->format = AUDIO_S16LSB; break; 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: default:
test_format = SDL_NextAudioFormat();
break;
}
}
if (!valid_datatype) { /* shouldn't happen, but just in case... */
SDL_SetError("Unsupported audio format"); SDL_SetError("Unsupported audio format");
return(-1); return (-1);
} }
if (spec->channels > 2)
spec->channels = 2; /* no more than stereo on the Dreamcast. */
/* Update the fragment size as size in bytes */ /* Update the fragment size as size in bytes */
SDL_CalculateAudioSpec(spec); SDL_CalculateAudioSpec(spec);
......
...@@ -139,78 +139,104 @@ static void AL_CloseAudio(_THIS) ...@@ -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 #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 #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 #endif
int width;
/* Determine the audio parameters from the AudioSpec */ while ((!valid) && (test_format)) {
switch ( spec->format & 0xFF ) { valid = 1;
spec->format = test_format;
case 8: { /* Signed 8 bit audio data */ switch (test_format) {
spec->format = AUDIO_S8; case AUDIO_S8:
width = AL_SAMPLE_8; width = AL_SAMPLE_8;
} fmt = AL_SAMPFMT_TWOSCOMP;
break; break;
case 16: { /* Signed 16 bit audio data */ case AUDIO_S16SYS:
spec->format = AUDIO_S16MSB;
width = AL_SAMPLE_16; width = AL_SAMPLE_16;
} fmt = AL_SAMPFMT_TWOSCOMP;
break; break;
default: { default:
SDL_SetError("Unsupported audio format"); valid = 0;
return(-1); test_format = SDL_NextAudioFormat();
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. */
} }
} }
/* Update the fragment size as size in bytes */ if ((alSetSampFmt(audio_config, fmt) >= 0) &&
SDL_CalculateAudioSpec(spec); ((!width) || (alSetWidth(audio_config, width) >= 0)) &&
(alSetQueueSize(audio_config, spec->samples * 2) >= 0) &&
(alSetChannels(audio_config, spec->channels) >= 0)) {
/* Set output frequency */ audio_port = alOpenPort("SDL audio", "w", audio_config);
#ifdef OLD_IRIX_AUDIO if (audio_port == NULL) {
audio_param[0] = AL_OUTPUT_RATE; /* docs say AL_BAD_CHANNELS happens here, too. */
audio_param[1] = spec->freq; int err = oserror();
if( ALsetparams(AL_DEFAULT_DEVICE, audio_param, 2) < 0 ) { if (err == AL_BAD_CHANNELS) {
#else spec->channels = 2;
audio_param.param = AL_RATE; alSetChannels(audio_config, spec->channels);
audio_param.value.i = spec->freq; audio_port = alOpenPort("SDL audio", "w",
if( alSetParams(AL_DEFAULT_OUTPUT, &audio_param, 1) < 0 ) { audio_config);
#endif }
SDL_SetError("alSetParams failed");
return(-1);
} }
/* Open the audio port with the requested frequency */ if (audio_port != NULL) {
audio_port = NULL; valid = 1;
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); alFreeConfig(audio_config);
if( audio_port == NULL ) { }
SDL_SetError("Unable to open audio port"); }
return(-1);
} }
if (!valid) {
SDL_SetError("Unsupported audio format");
return (-1);
}
/* Update the fragment size as size in bytes */
SDL_CalculateAudioSpec(spec);
/* Allocate mixing buffer */ /* Allocate mixing buffer */
mixbuf = (Uint8 *)SDL_AllocAudioMem(spec->size); mixbuf = (Uint8 *) SDL_AllocAudioMem(spec->size);
if ( mixbuf == NULL ) { if (mixbuf == NULL) {
SDL_OutOfMemory(); SDL_OutOfMemory();
return(-1); return (-1);
} }
SDL_memset(mixbuf, spec->silence, spec->size); SDL_memset(mixbuf, spec->silence, spec->size);
/* We're ready to rock and roll. :-) */ /* We're ready to rock and roll. :-) */
return(0); return (0);
} }
...@@ -217,6 +217,9 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) ...@@ -217,6 +217,9 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
DEBUG_PRINT(("channels=%d, ", spec->channels)); DEBUG_PRINT(("channels=%d, ", spec->channels));
DEBUG_PRINT(("freq=%d\n", spec->freq)); DEBUG_PRINT(("freq=%d\n", spec->freq));
if (spec->channels > 2)
spec->channels = 2;
/* Check formats available */ /* Check formats available */
spec->format = AUDIO_S8; spec->format = AUDIO_S8;
......
...@@ -201,6 +201,8 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) ...@@ -201,6 +201,8 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
{ {
long snd_format; long snd_format;
int i, resolution, format_signed, format_bigendian; int i, resolution, format_signed, format_bigendian;
SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
int valid_datatype = 0;
resolution = spec->format & 0x00ff; resolution = spec->format & 0x00ff;
format_signed = ((spec->format & 0x8000)!=0); format_signed = ((spec->format & 0x8000)!=0);
...@@ -212,28 +214,46 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) ...@@ -212,28 +214,46 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
DEBUG_PRINT(("channels=%d, ", spec->channels)); DEBUG_PRINT(("channels=%d, ", spec->channels));
DEBUG_PRINT(("freq=%d\n", spec->freq)); DEBUG_PRINT(("freq=%d\n", spec->freq));
if (spec->channels > 2) {
spec->channels = 2; /* no more than stereo! */
}
while ((!valid_datatype) && (test_format)) {
/* Check formats available */ /* Check formats available */
snd_format = Sndstatus(SND_QUERYFORMATS); snd_format = Sndstatus(SND_QUERYFORMATS);
switch (resolution) { spec->format = test_format;
case 8: resolution = SDL_AUDIO_BITSIZE(spec->format);
if ((snd_format & SND_FORMAT8)==0) { format_signed = SDL_AUDIO_ISSIGNED(spec->format);
SDL_SetError("Mint_CheckAudio: 8 bits samples not supported"); format_bigendian = SDL_AUDIO_ISBIGENDIAN(spec->format);
return -1; switch (test_format) {
} case AUDIO_U8:
case AUDIO_S8:
if (snd_format & SND_FORMAT8) {
valid_datatype = 1;
snd_format = Sndstatus(SND_QUERY8BIT); 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;
} }
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); snd_format = Sndstatus(SND_QUERY16BIT);
}
break; break;
default: default:
SDL_SetError("Mint_CheckAudio: Unsupported sample resolution"); test_format = SDL_NextAudioFormat();
return -1;
break; break;
} }
}
if (!valid_datatype) {
SDL_SetError("Unsupported audio format");
return (-1);
}
/* Check signed/unsigned format */ /* Check signed/unsigned format */
if (format_signed) { if (format_signed) {
......
...@@ -224,6 +224,10 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) ...@@ -224,6 +224,10 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
DEBUG_PRINT(("channels=%d, ", spec->channels)); DEBUG_PRINT(("channels=%d, ", spec->channels));
DEBUG_PRINT(("freq=%d\n", spec->freq)); DEBUG_PRINT(("freq=%d\n", spec->freq));
if (spec->channels > 2) {
spec->channels = 2; /* no more than stereo! */
}
/* Check formats available */ /* Check formats available */
MINTAUDIO_freqcount=0; MINTAUDIO_freqcount=0;
switch(cookie_mcsn->play) { switch(cookie_mcsn->play) {
......
...@@ -205,6 +205,10 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) ...@@ -205,6 +205,10 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
DEBUG_PRINT(("channels=%d, ", spec->channels)); DEBUG_PRINT(("channels=%d, ", spec->channels));
DEBUG_PRINT(("freq=%d\n", spec->freq)); DEBUG_PRINT(("freq=%d\n", spec->freq));
if (spec->channels > 2) {
spec->channels = 2; /* no more than stereo! */
}
/* Check formats available */ /* Check formats available */
MINTAUDIO_freqcount=0; MINTAUDIO_freqcount=0;
for (i=0;i<16;i++) { for (i=0;i<16;i++) {
......
...@@ -341,6 +341,10 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) ...@@ -341,6 +341,10 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
DEBUG_PRINT(("channels=%d, ", spec->channels)); DEBUG_PRINT(("channels=%d, ", spec->channels));
DEBUG_PRINT(("freq=%d\n", spec->freq)); 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 */ spec->format |= 0x8000; /* Audio is always signed */
if ((spec->format & 0x00ff)==16) { if ((spec->format & 0x00ff)==16) {
spec->format |= 0x1000; /* Audio is always big endian */ spec->format |= 0x1000; /* Audio is always big endian */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment