audio: Readd SDL_AudioSpec, but just with format/channels/freq fields.

This commit is contained in:
Ryan C. Gordon 2023-05-30 01:08:22 -04:00
parent e6aaed7d79
commit 26525f5fd3
No known key found for this signature in database
GPG Key ID: FA148B892AB48044
12 changed files with 244 additions and 287 deletions

View File

@ -152,7 +152,7 @@ SDL_QueueAudio(), SDL_DequeueAudio, and SDL_ClearQueuedAudio and SDL_GetQueuedAu
APIs that use channel counts used to use a Uint8 for the channel; now they use int.
SDL_AudioSpec has been removed; things that used it have simply started taking separate arguments for format, channel, and sample rate. SDL_GetSilenceValueForFormat() can provide the information from the SDL_AudioSpec's `silence` field. The other SDL_AudioSpec fields aren't relevant anymore.
SDL_AudioSpec has been reduced; now it only holds format, channel, and sample rate. SDL_GetSilenceValueForFormat() can provide the information from the SDL_AudioSpec's `silence` field. The other SDL2 SDL_AudioSpec fields aren't relevant anymore.
SDL_GetAudioDeviceSpec() is removed; use SDL_GetAudioDeviceFormat() instead.

View File

@ -141,6 +141,13 @@ typedef Uint16 SDL_AudioFormat;
/* @} *//* Audio flags */
typedef struct SDL_AudioSpec
{
SDL_AudioFormat format; /**< Audio data format */
int channels; /**< Number of channels: 1 mono, 2 stereo, etc */
int freq; /**< sample rate: sample frames per second */
} SDL_AudioSpec;
/* SDL_AudioStream is an audio conversion interface.
- It can handle resampling data in chunks without generating
artifacts, when it doesn't have the complete buffer available.
@ -305,9 +312,7 @@ extern DECLSPEC char *SDLCALL SDL_GetAudioDeviceName(SDL_AudioDeviceID devid);
* can't be determined).
*
* \param devid the instance ID of the device to query.
* \param fmt On return, will be set to the device's data format. Can be NULL.
* \param channels On return, will be set to the device's channel count. Can be NULL.
* \param freq On return, will be set to the device's sample rate. Can be NULL.
* \param spec On return, will be filled with device details.
* \returns 0 on success or a negative error code on failure; call
* SDL_GetError() for more information.
*
@ -315,7 +320,7 @@ extern DECLSPEC char *SDLCALL SDL_GetAudioDeviceName(SDL_AudioDeviceID devid);
*
* \since This function is available since SDL 3.0.0.
*/
extern DECLSPEC int SDLCALL SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioFormat *fmt, int *channels, int *freq);
extern DECLSPEC int SDLCALL SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec);
/**
@ -362,9 +367,7 @@ extern DECLSPEC int SDLCALL SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SD
*
* \param devid the device instance id to open. 0 requests the most
* reasonable default device.
* \param fmt the requested device format (`SDL_AUDIO_S16`, etc)
* \param channels the requested device channels (1==mono, 2==stereo, etc).
* \param freq the requested device frequency in sample-frames-per-second (Hz)
* \param spec the requested device configuration
* \returns The device ID on success, 0 on error; call SDL_GetError() for more information.
*
* \since This function is available since SDL 3.0.0.
@ -374,7 +377,7 @@ extern DECLSPEC int SDLCALL SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SD
* \sa SDL_CloseAudioDevice
* \sa SDL_GetAudioDeviceFormat
*/
extern DECLSPEC SDL_AudioDeviceID SDLCALL SDL_OpenAudioDevice(SDL_AudioDeviceID devid, SDL_AudioFormat fmt, int channels, int freq);
extern DECLSPEC SDL_AudioDeviceID SDLCALL SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSpec *spec);
/**
@ -499,12 +502,8 @@ extern DECLSPEC void SDLCALL SDL_UnbindAudioStream(SDL_AudioStream *stream);
/**
* Create a new audio stream.
*
* \param src_format The format of the source audio
* \param src_channels The number of channels of the source audio
* \param src_rate The sampling rate of the source audio
* \param dst_format The format of the desired audio output
* \param dst_channels The number of channels of the desired audio output
* \param dst_rate The sampling rate of the desired audio output
* \param src_spec The format details of the input audio
* \param dst_spec The format details of the output audio
* \returns 0 on success, or -1 on error.
*
* \threadsafety It is safe to call this function from any thread.
@ -519,26 +518,15 @@ extern DECLSPEC void SDLCALL SDL_UnbindAudioStream(SDL_AudioStream *stream);
* \sa SDL_ChangeAudioStreamOutput
* \sa SDL_DestroyAudioStream
*/
extern DECLSPEC SDL_AudioStream *SDLCALL SDL_CreateAudioStream(SDL_AudioFormat src_format,
int src_channels,
int src_rate,
SDL_AudioFormat dst_format,
int dst_channels,
int dst_rate);
extern DECLSPEC SDL_AudioStream *SDLCALL SDL_CreateAudioStream(const SDL_AudioSpec *src_spec, const SDL_AudioSpec *dst_spec);
/**
* Query the current format of an audio stream.
*
* \param stream the SDL_AudioStream to query.
* \param src_format Where to store the input audio format; ignored if NULL.
* \param src_channels Where to store the input channel count; ignored if
* NULL.
* \param src_rate Where to store the input sample rate; ignored if NULL.
* \param dst_format Where to store the output audio format; ignored if NULL.
* \param dst_channels Where to store the output channel count; ignored if
* NULL.
* \param dst_rate Where to store the output sample rate; ignored if NULL.
* \param src_spec Where to store the input audio format; ignored if NULL.
* \param dst_spec Where to store the output audio format; ignored if NULL.
* \returns 0 on success, or -1 on error.
*
* \threadsafety It is safe to call this function from any thread, as it holds
@ -547,12 +535,8 @@ extern DECLSPEC SDL_AudioStream *SDLCALL SDL_CreateAudioStream(SDL_AudioFormat s
* \since This function is available since SDL 3.0.0.
*/
extern DECLSPEC int SDLCALL SDL_GetAudioStreamFormat(SDL_AudioStream *stream,
SDL_AudioFormat *src_format,
int *src_channels,
int *src_rate,
SDL_AudioFormat *dst_format,
int *dst_channels,
int *dst_rate);
SDL_AudioSpec *src_spec,
SDL_AudioSpec *dst_spec);
/**
* Change the input and output formats of an audio stream.
@ -562,12 +546,8 @@ extern DECLSPEC int SDLCALL SDL_GetAudioStreamFormat(SDL_AudioStream *stream,
* must provide data in the new input formats.
*
* \param stream The stream the format is being changed
* \param src_format The format of the audio input
* \param src_channels The number of channels of the audio input
* \param src_rate The sampling rate of the audio input
* \param dst_format The format of the desired audio output
* \param dst_channels The number of channels of the desired audio output
* \param dst_rate The sampling rate of the desired audio output
* \param src_spec The new format of the audio input; if NULL, it is not changed.
* \param dst_spec The new format of the audio output; if NULL, it is not changed.
* \returns 0 on success, or -1 on error.
*
* \threadsafety It is safe to call this function from any thread, as it holds
@ -581,12 +561,8 @@ extern DECLSPEC int SDLCALL SDL_GetAudioStreamFormat(SDL_AudioStream *stream,
* \sa SDL_GetAudioStreamAvailable
*/
extern DECLSPEC int SDLCALL SDL_SetAudioStreamFormat(SDL_AudioStream *stream,
SDL_AudioFormat src_format,
int src_channels,
int src_rate,
SDL_AudioFormat dst_format,
int dst_channels,
int dst_rate);
const SDL_AudioSpec *src_spec,
const SDL_AudioSpec *dst_spec);
/**
* Add data to be converted/resampled to the stream.
@ -902,15 +878,13 @@ extern DECLSPEC void SDLCALL SDL_DestroyAudioStream(SDL_AudioStream *stream);
* correctly to match both the app and the audio device's needs. This is
* optional, but slightly less cumbersome to set up for a common use case.
*
* The format parameters (`fmt`, `channels`, `freq`) represent the app's side
* of the audio stream. That is, for recording audio, this will be the output
* format, and for playing audio, this will be the input format. This function
* will set the other side of the audio stream to the device's format.
* The `spec` parameter represents the app's side of the audio stream. That
* is, for recording audio, this will be the output format, and for playing
* audio, this will be the input format. This function will set the other
* side of the audio stream to the device's format.
*
* \param devid an audio device to bind a stream to. This must be an opened device, and can not be zero.
* \param fmt the audio stream's format (`SDL_AUDIO_S16`, etc)
* \param channels the audio stream's channel count (1==mono, 2==stereo, etc).
* \param freq the audio stream's frequency in sample-frames-per-second (Hz)
* \param spec the audio stream's input format
* \returns a bound audio stream on success, ready to use. NULL on error; call SDL_GetError() for more information.
*
* \since This function is available since SDL 3.0.0.
@ -921,7 +895,7 @@ extern DECLSPEC void SDLCALL SDL_DestroyAudioStream(SDL_AudioStream *stream);
* \sa SDL_UnbindAudioStreams
* \sa SDL_UnbindAudioStream
*/
extern DECLSPEC SDL_AudioStream *SDLCALL SDL_CreateAndBindAudioStream(SDL_AudioDeviceID devid, SDL_AudioFormat fmt, int channels, int freq);
extern DECLSPEC SDL_AudioStream *SDLCALL SDL_CreateAndBindAudioStream(SDL_AudioDeviceID devid, const SDL_AudioSpec *spec);
/**
@ -981,12 +955,8 @@ extern DECLSPEC SDL_AudioStream *SDLCALL SDL_CreateAndBindAudioStream(SDL_AudioD
*
* \param src The data source for the WAVE data
* \param freesrc If non-zero, SDL will _always_ free the data source
* \param fmt A pointer to an SDL_AudioFormat that will be set to the
* WAVE data's format on successful return.
* \param channels A pointer to an int that will be set to the
* WAVE data's channel count on successful return.
* \param freq A pointer to an int that will be set to the
* WAVE data's sample rate in Hz on successful return.
* \param spec A pointer to an SDL_AudioSpec that will be set to the
* WAVE data's format details on successful return.
* \param audio_buf A pointer filled with the audio data, allocated by the
* function.
* \param audio_len A pointer filled with the length of the audio data buffer
@ -1009,8 +979,7 @@ extern DECLSPEC SDL_AudioStream *SDLCALL SDL_CreateAndBindAudioStream(SDL_AudioD
* \sa SDL_LoadWAV
*/
extern DECLSPEC int SDLCALL SDL_LoadWAV_RW(SDL_RWops * src, int freesrc,
SDL_AudioFormat *fmt, int *channels, int *freq,
Uint8 ** audio_buf,
SDL_AudioSpec * spec, Uint8 ** audio_buf,
Uint32 * audio_len);
/**
@ -1074,14 +1043,10 @@ extern DECLSPEC int SDLCALL SDL_MixAudioFormat(Uint8 * dst,
* use, so it's also less efficient than using one directly, if you need to
* convert multiple times.
*
* \param src_format The format of the source audio
* \param src_channels The number of channels of the source audio
* \param src_rate The sampling rate of the source audio
* \param src_spec The format details of the input audio
* \param src_data The audio data to be converted
* \param src_len The len of src_data
* \param dst_format The format of the desired audio output
* \param dst_channels The number of channels of the desired audio output
* \param dst_rate The sampling rate of the desired audio output
* \param dst_spec The format details of the output audio
* \param dst_data Will be filled with a pointer to converted audio data,
* which should be freed with SDL_free(). On error, it will be
* NULL.
@ -1093,14 +1058,10 @@ extern DECLSPEC int SDLCALL SDL_MixAudioFormat(Uint8 * dst,
*
* \sa SDL_CreateAudioStream
*/
extern DECLSPEC int SDLCALL SDL_ConvertAudioSamples(SDL_AudioFormat src_format,
int src_channels,
int src_rate,
extern DECLSPEC int SDLCALL SDL_ConvertAudioSamples(const SDL_AudioSpec *src_spec,
const Uint8 *src_data,
int src_len,
SDL_AudioFormat dst_format,
int dst_channels,
int dst_rate,
const SDL_AudioSpec *dst_spec,
Uint8 **dst_data,
int *dst_len);

View File

@ -169,7 +169,7 @@ static void DestroyAudioDevice(SDL_AudioDevice *device)
SDL_free(device);
}
static SDL_AudioDevice *CreateAudioDevice(const char *name, SDL_bool iscapture, SDL_AudioFormat fmt, int channels, int freq, void *handle, SDL_AudioDevice **devices, SDL_AtomicInt *device_count)
static SDL_AudioDevice *CreateAudioDevice(const char *name, SDL_bool iscapture, const SDL_AudioSpec *spec, void *handle, SDL_AudioDevice **devices, SDL_AtomicInt *device_count)
{
SDL_AudioDevice *device;
@ -202,10 +202,9 @@ static SDL_AudioDevice *CreateAudioDevice(const char *name, SDL_bool iscapture,
SDL_AtomicSet(&device->shutdown, 0);
SDL_AtomicSet(&device->condemned, 0);
device->iscapture = iscapture;
device->format = device->default_format = fmt;
device->channels = device->default_channels = channels;
device->freq = device->default_freq = freq;
device->silence_value = SDL_GetSilenceValueForFormat(device->format);
SDL_memcpy(&device->spec, spec, sizeof (SDL_AudioSpec));
SDL_memcpy(&device->default_spec, spec, sizeof (SDL_AudioSpec));
device->silence_value = SDL_GetSilenceValueForFormat(device->spec.format);
device->handle = handle;
device->prev = NULL;
@ -225,33 +224,34 @@ static SDL_AudioDevice *CreateAudioDevice(const char *name, SDL_bool iscapture,
return device;
}
static SDL_AudioDevice *CreateAudioCaptureDevice(const char *name, SDL_AudioFormat fmt, int channels, int freq, void *handle)
static SDL_AudioDevice *CreateAudioCaptureDevice(const char *name, const SDL_AudioSpec *spec, void *handle)
{
SDL_assert(current_audio.impl.HasCaptureSupport);
return CreateAudioDevice(name, SDL_TRUE, fmt, channels, freq, handle, &current_audio.capture_devices, &current_audio.capture_device_count);
return CreateAudioDevice(name, SDL_TRUE, spec, handle, &current_audio.capture_devices, &current_audio.capture_device_count);
}
static SDL_AudioDevice *CreateAudioOutputDevice(const char *name, SDL_AudioFormat fmt, int channels, int freq, void *handle)
static SDL_AudioDevice *CreateAudioOutputDevice(const char *name, const SDL_AudioSpec *spec, void *handle)
{
return CreateAudioDevice(name, SDL_FALSE, fmt, channels, freq, handle, &current_audio.output_devices, &current_audio.output_device_count);
return CreateAudioDevice(name, SDL_FALSE, spec, handle, &current_audio.output_devices, &current_audio.output_device_count);
}
/* The audio backends call this when a new device is plugged in. */
SDL_AudioDevice *SDL_AddAudioDevice(const SDL_bool iscapture, const char *name, SDL_AudioFormat fmt, int channels, int freq, void *handle)
SDL_AudioDevice *SDL_AddAudioDevice(const SDL_bool iscapture, const char *name, const SDL_AudioSpec *inspec, void *handle)
{
SDL_AudioDevice *device;
SDL_AudioSpec spec;
if (fmt == 0) {
fmt = DEFAULT_AUDIO_FORMAT;
}
if (channels == 0) {
channels = DEFAULT_AUDIO_CHANNELS;
}
if (freq == 0) {
freq = DEFAULT_AUDIO_FREQUENCY;
if (!inspec) {
spec.format = DEFAULT_AUDIO_FORMAT;
spec.channels = DEFAULT_AUDIO_CHANNELS;
spec.freq = DEFAULT_AUDIO_FREQUENCY;
} else {
spec.format = (inspec->format != 0) ? inspec->format : DEFAULT_AUDIO_FORMAT;
spec.channels = (inspec->channels != 0) ? inspec->channels : DEFAULT_AUDIO_CHANNELS;
spec.freq = (inspec->freq != 0) ? inspec->freq : DEFAULT_AUDIO_FREQUENCY;
}
device = iscapture ? CreateAudioCaptureDevice(name, fmt, channels, freq, handle) : CreateAudioOutputDevice(name, fmt, channels, freq, handle);
device = iscapture ? CreateAudioCaptureDevice(name, &spec, handle) : CreateAudioOutputDevice(name, &spec, handle);
if (device) {
/* Post the event, if desired */
if (SDL_EventEnabled(SDL_EVENT_AUDIO_DEVICE_ADDED)) {
@ -330,9 +330,9 @@ static void SDL_AudioDetectDevices_Default(void)
SDL_assert(current_audio.impl.OnlyHasDefaultOutputDevice);
SDL_assert(current_audio.impl.OnlyHasDefaultCaptureDevice || !current_audio.impl.HasCaptureSupport);
SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, 0, 0, 0, (void *)((size_t)0x1));
SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, NULL, (void *)((size_t)0x1));
if (current_audio.impl.HasCaptureSupport) {
SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, 0, 0, 0, (void *)((size_t)0x2));
SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, NULL, (void *)((size_t)0x2));
}
}
@ -614,7 +614,7 @@ SDL_bool SDL_OutputAudioThreadIterate(SDL_AudioDevice *device)
retval = SDL_FALSE;
break;
} else if (br > 0) { /* it's okay if we get less than requested, we mix what we have. */
if (SDL_MixAudioFormat(mix_buffer, device->work_buffer, device->format, br, SDL_MIX_MAXVOLUME) < 0) { /* !!! FIXME: allow streams to specify gain? */
if (SDL_MixAudioFormat(mix_buffer, device->work_buffer, device->spec.format, br, SDL_MIX_MAXVOLUME) < 0) { /* !!! FIXME: allow streams to specify gain? */
SDL_assert(!"We probably ended up with some totally unexpected audio format here");
retval = SDL_FALSE; /* uh...? */
break;
@ -636,10 +636,10 @@ SDL_bool SDL_OutputAudioThreadIterate(SDL_AudioDevice *device)
void SDL_OutputAudioThreadShutdown(SDL_AudioDevice *device)
{
const int samples = (device->buffer_size / (SDL_AUDIO_BITSIZE(device->format) / 8)) / device->channels;
const int samples = (device->buffer_size / (SDL_AUDIO_BITSIZE(device->spec.format) / 8)) / device->spec.channels;
SDL_assert(!device->iscapture);
/* Wait for the audio to drain. */ /* !!! FIXME: don't bother waiting if device is lost. */
SDL_Delay(((samples * 1000) / device->freq) * 2);
SDL_Delay(((samples * 1000) / device->spec.freq) * 2);
current_audio.impl.ThreadDeinit(device);
if (SDL_AtomicGet(&device->condemned)) {
SDL_DetachThread(device->thread); /* no one is waiting for us, just detach ourselves. */
@ -878,23 +878,18 @@ char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid)
return retval;
}
int SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioFormat *fmt, int *channels, int *freq)
int SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec)
{
if (!spec) {
return SDL_InvalidParamError("spec");
}
SDL_AudioDevice *device = ObtainAudioDevice(devid);
if (!device) {
return -1;
}
if (fmt) {
*fmt = device->format;
}
if (channels) {
*channels = device->channels;
}
if (freq) {
*freq = device->freq;
}
SDL_memcpy(spec, &device->spec, sizeof (SDL_AudioSpec));
SDL_UnlockMutex(device->lock);
return 0;
@ -917,11 +912,9 @@ static void CloseAudioDevice(SDL_AudioDevice *device)
device->work_buffer = NULL;
}
device->format = device->default_format;
device->channels = device->default_channels;
device->freq = device->default_freq;
SDL_memcpy(&device->spec, &device->default_spec, sizeof (SDL_AudioSpec));
device->sample_frames = 0;
device->silence_value = SDL_GetSilenceValueForFormat(device->format);
device->silence_value = SDL_GetSilenceValueForFormat(device->spec.format);
}
void SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
@ -965,35 +958,35 @@ static SDL_AudioFormat ParseAudioFormatString(const char *string)
return 0;
}
static void PrepareAudioFormat(SDL_AudioFormat *fmt, int *channels, int *freq)
static void PrepareAudioFormat(SDL_AudioSpec *spec)
{
const char *env;
if (*freq == 0) {
*freq = DEFAULT_AUDIO_FREQUENCY;
env = SDL_getenv("SDL_AUDIO_FREQUENCY");
if (spec->freq == 0) {
spec->freq = DEFAULT_AUDIO_FREQUENCY;
env = SDL_getenv("SDL_AUDIO_FREQUENCY"); // !!! FIXME: should be a hint?
if (env != NULL) {
const int val = SDL_atoi(env);
if (val > 0) {
*freq = val;
spec->freq = val;
}
}
}
if (*channels == 0) {
*channels = DEFAULT_AUDIO_CHANNELS;
if (spec->channels == 0) {
spec->channels = DEFAULT_AUDIO_CHANNELS;
env = SDL_getenv("SDL_AUDIO_CHANNELS");
if (env != NULL) {
const int val = SDL_atoi(env);
if (val > 0) {
*channels = val;
spec->channels = val;
}
}
}
if (*fmt == 0) {
if (spec->format == 0) {
const SDL_AudioFormat val = ParseAudioFormatString(SDL_getenv("SDL_AUDIO_FORMAT"));
*fmt = (val != 0) ? val : DEFAULT_AUDIO_FORMAT;
spec->format = (val != 0) ? val : DEFAULT_AUDIO_FORMAT;
}
}
@ -1010,25 +1003,27 @@ static int GetDefaultSampleFramesFromFreq(int freq)
void SDL_UpdatedAudioDeviceFormat(SDL_AudioDevice *device)
{
device->silence_value = SDL_GetSilenceValueForFormat(device->format);
device->buffer_size = device->sample_frames * (SDL_AUDIO_BITSIZE(device->format) / 8) * device->channels;
device->silence_value = SDL_GetSilenceValueForFormat(device->spec.format);
device->buffer_size = device->sample_frames * (SDL_AUDIO_BITSIZE(device->spec.format) / 8) * device->spec.channels;
}
/* this expects the device lock to be held. */
static int OpenAudioDevice(SDL_AudioDevice *device, SDL_AudioFormat fmt, int channels, int freq)
static int OpenAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec *inspec)
{
SDL_assert(SDL_AtomicGet(&device->refcount) == 1);
PrepareAudioFormat(&fmt, &channels, &freq);
SDL_AudioSpec spec;
SDL_memcpy(&spec, inspec, sizeof (SDL_AudioSpec));
PrepareAudioFormat(&spec);
/* we allow the device format to change if it's better than the current settings (by various definitions of "better"). This prevents
something low quality, like an old game using S8/8000Hz audio, from ruining a music thing playing at CD quality that tries to open later.
(or some VoIP library that opens for mono output ruining your surround-sound game because it got there first). */
/* These are just requests! The backend may change any of these values during OpenDevice method! */
device->format = (SDL_AUDIO_BITSIZE(device->default_format) >= SDL_AUDIO_BITSIZE(fmt)) ? device->default_format : fmt;
device->freq = SDL_max(device->default_freq, freq);
device->channels = SDL_max(device->default_channels, channels);
device->sample_frames = GetDefaultSampleFramesFromFreq(device->freq);
device->spec.format = (SDL_AUDIO_BITSIZE(device->default_spec.format) >= SDL_AUDIO_BITSIZE(spec.format)) ? device->default_spec.format : spec.format;
device->spec.freq = SDL_max(device->default_spec.freq, spec.freq);
device->spec.channels = SDL_max(device->default_spec.channels, spec.channels);
device->sample_frames = GetDefaultSampleFramesFromFreq(device->spec.freq);
SDL_UpdatedAudioDeviceFormat(device); /* start this off sane. */
if (current_audio.impl.OpenDevice(device) < 0) {
@ -1062,7 +1057,7 @@ static int OpenAudioDevice(SDL_AudioDevice *device, SDL_AudioFormat fmt, int cha
return 0;
}
SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, SDL_AudioFormat fmt, int channels, int freq)
SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSpec *spec)
{
SDL_AudioDevice *device = ObtainAudioDevice(devid); /* !!! FIXME: need to choose default device for devid==0 */
int retval = 0;
@ -1070,7 +1065,7 @@ SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, SDL_AudioFormat f
if (device) {
retval = device->instance_id;
if (SDL_AtomicIncRef(&device->refcount) == 0) {
if (OpenAudioDevice(device, fmt, channels, freq) == -1) {
if (OpenAudioDevice(device, spec) == -1) {
retval = 0;
}
}
@ -1127,16 +1122,14 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int
/* Now that everything is verified, chain everything together. */
for (i = 0; i < num_streams; i++) {
SDL_AudioStream *stream = streams[i];
SDL_AudioFormat src_format, dst_format;
int src_channels, dst_channels;
int src_rate, dst_rate;
SDL_AudioSpec src_spec, dst_spec;
/* set the proper end of the stream to the device's format. */
SDL_GetAudioStreamFormat(stream, &src_format, &src_channels, &src_rate, &dst_format, &dst_channels, &dst_rate);
SDL_GetAudioStreamFormat(stream, &src_spec, &dst_spec);
if (device->iscapture) {
SDL_SetAudioStreamFormat(stream, device->format, device->channels, device->freq, dst_format, dst_channels, dst_rate);
SDL_SetAudioStreamFormat(stream, &device->spec, &dst_spec);
} else {
SDL_SetAudioStreamFormat(stream, src_format, src_channels, src_rate, device->format, device->channels, device->freq);
SDL_SetAudioStreamFormat(stream, &src_spec, &device->spec);
}
stream->bound_device = device;
@ -1236,16 +1229,16 @@ void SDL_UnbindAudioStream(SDL_AudioStream *stream)
}
SDL_AudioStream *SDL_CreateAndBindAudioStream(SDL_AudioDeviceID devid, SDL_AudioFormat fmt, int channels, int freq)
SDL_AudioStream *SDL_CreateAndBindAudioStream(SDL_AudioDeviceID devid, const SDL_AudioSpec *spec)
{
SDL_AudioStream *stream = NULL;
SDL_AudioDevice *device = ObtainAudioDevice(devid);
if (device) {
const SDL_bool iscapture = (devid & 1) ? SDL_FALSE : SDL_TRUE; /* capture instance ids are even and output devices are odd */
if (iscapture) {
stream = SDL_CreateAudioStream(device->format, device->channels, device->freq, fmt, channels, freq);
stream = SDL_CreateAudioStream(&device->spec, spec);
} else {
stream = SDL_CreateAudioStream(fmt, channels, freq, device->format, device->channels, device->freq);
stream = SDL_CreateAudioStream(spec, &device->spec);
}
if (stream) {

View File

@ -446,13 +446,20 @@ static int CalculateMaxSampleFrameSize(SDL_AudioFormat src_format, int src_chann
}
/* this assumes you're holding the stream's lock (or are still creating the stream). */
static int SetAudioStreamFormat(SDL_AudioStream *stream, SDL_AudioFormat src_format, int src_channels, int src_rate, SDL_AudioFormat dst_format, int dst_channels, int dst_rate)
static int SetAudioStreamFormat(SDL_AudioStream *stream, const SDL_AudioSpec *src_spec, const SDL_AudioSpec *dst_spec)
{
/* If increasing channels, do it after resampling, since we'd just
do more work to resample duplicate channels. If we're decreasing, do
it first so we resample the interpolated data instead of interpolating
the resampled data (!!! FIXME: decide if that works in practice, though!).
This is decided in pre_resample_channels. */
const SDL_AudioFormat src_format = src_spec->format;
const int src_channels = src_spec->channels;
const int src_rate = src_spec->freq;
const SDL_AudioFormat dst_format = dst_spec->format;
const int dst_channels = dst_spec->channels;
const int dst_rate = dst_spec->freq;
const int src_sample_frame_size = (SDL_AUDIO_BITSIZE(src_format) / 8) * src_channels;
const int dst_sample_frame_size = (SDL_AUDIO_BITSIZE(dst_format) / 8) * dst_channels;
const int max_sample_frame_size = CalculateMaxSampleFrameSize(src_format, src_channels, dst_format, dst_channels);
@ -515,16 +522,16 @@ static int SetAudioStreamFormat(SDL_AudioStream *stream, SDL_AudioFormat src_for
/* copy to new buffers and/or convert data; ConvertAudio will do a simple memcpy if format matches, and nothing at all if the buffer hasn't changed */
if (stream->future_buffer) {
ConvertAudio(stream->future_buffer_filled_frames, stream->future_buffer, stream->src_format, stream->src_channels, future_buffer, src_format, src_channels);
ConvertAudio(stream->future_buffer_filled_frames, stream->future_buffer, stream->src_spec.format, stream->src_spec.channels, future_buffer, src_format, src_channels);
} else if (future_buffer != NULL) {
SDL_memset(future_buffer, SDL_GetSilenceValueForFormat(src_format), future_buffer_allocation);
}
if (stream->history_buffer) {
if (history_buffer_frames <= prev_history_buffer_frames) {
ConvertAudio(history_buffer_frames, stream->history_buffer, stream->src_format, stream->src_channels, history_buffer, src_format, src_channels);
ConvertAudio(history_buffer_frames, stream->history_buffer, stream->src_spec.format, stream->src_spec.channels, history_buffer, src_format, src_channels);
} else {
ConvertAudio(prev_history_buffer_frames, stream->history_buffer, stream->src_format, stream->src_channels, history_buffer + ((history_buffer_frames - prev_history_buffer_frames) * src_sample_frame_size), src_format, src_channels);
ConvertAudio(prev_history_buffer_frames, stream->history_buffer, stream->src_spec.format, stream->src_spec.channels, history_buffer + ((history_buffer_frames - prev_history_buffer_frames) * src_sample_frame_size), src_format, src_channels);
SDL_memset(history_buffer, SDL_GetSilenceValueForFormat(src_format), (history_buffer_frames - prev_history_buffer_frames) * src_sample_frame_size); /* silence oldest history samples. */
}
} else if (history_buffer != NULL) {
@ -547,53 +554,56 @@ static int SetAudioStreamFormat(SDL_AudioStream *stream, SDL_AudioFormat src_for
stream->history_buffer_frames = history_buffer_frames;
stream->max_sample_frame_size = max_sample_frame_size;
stream->src_sample_frame_size = src_sample_frame_size;
stream->src_format = src_format;
stream->src_channels = src_channels;
stream->src_rate = src_rate;
stream->dst_sample_frame_size = dst_sample_frame_size;
stream->dst_format = dst_format;
stream->dst_channels = dst_channels;
stream->dst_rate = dst_rate;
stream->pre_resample_channels = pre_resample_channels;
if (src_spec != &stream->src_spec) {
SDL_memcpy(&stream->src_spec, src_spec, sizeof (SDL_AudioSpec));
}
if (dst_spec != &stream->dst_spec) {
SDL_memcpy(&stream->dst_spec, dst_spec, sizeof (SDL_AudioSpec));
}
return 0;
}
SDL_AudioStream *SDL_CreateAudioStream(SDL_AudioFormat src_format,
int src_channels,
int src_rate,
SDL_AudioFormat dst_format,
int dst_channels,
int dst_rate)
SDL_AudioStream *SDL_CreateAudioStream(const SDL_AudioSpec *src_spec, const SDL_AudioSpec *dst_spec)
{
int packetlen = 4096; /* !!! FIXME: good enough for now. */
SDL_AudioStream *retval;
/* !!! FIXME: fail if audio isn't initialized? */
if (!SDL_IsSupportedChannelCount(src_channels)) {
SDL_InvalidParamError("src_channels");
if (!src_spec) {
SDL_InvalidParamError("src_spec");
return NULL;
} else if (!SDL_IsSupportedChannelCount(dst_channels)) {
SDL_InvalidParamError("dst_channels");
} else if (!dst_spec) {
SDL_InvalidParamError("dst_spec");
return NULL;
} else if (src_rate <= 0) {
SDL_InvalidParamError("src_rate");
} else if (!SDL_IsSupportedChannelCount(src_spec->channels)) {
SDL_InvalidParamError("src_spec->channels");
return NULL;
} else if (dst_rate <= 0) {
SDL_InvalidParamError("dst_rate");
} else if (!SDL_IsSupportedChannelCount(dst_spec->channels)) {
SDL_InvalidParamError("dst_spec->channels");
return NULL;
} else if (src_rate >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
} else if (src_spec->freq <= 0) {
SDL_InvalidParamError("src_spec->freq");
return NULL;
} else if (dst_spec->freq <= 0) {
SDL_InvalidParamError("dst_spec->freq");
return NULL;
} else if (src_spec->freq >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
SDL_SetError("Source rate is too high");
return NULL;
} else if (dst_rate >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
} else if (dst_spec->freq >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
SDL_SetError("Destination rate is too high");
return NULL;
} else if (!SDL_IsSupportedAudioFormat(src_format)) {
SDL_InvalidParamError("src_format");
} else if (!SDL_IsSupportedAudioFormat(src_spec->format)) {
SDL_InvalidParamError("src_spec->format");
return NULL;
} else if (!SDL_IsSupportedAudioFormat(dst_format)) {
SDL_InvalidParamError("dst_format");
} else if (!SDL_IsSupportedAudioFormat(dst_spec->format)) {
SDL_InvalidParamError("dst_spec->format");
return NULL;
}
@ -615,13 +625,11 @@ SDL_AudioStream *SDL_CreateAudioStream(SDL_AudioFormat src_format,
/* Make sure we've chosen audio conversion functions (SIMD, scalar, etc.) */
SDL_ChooseAudioConverters(); /* !!! FIXME: let's do this during SDL_Init? */
retval->src_sample_frame_size = (SDL_AUDIO_BITSIZE(src_format) / 8) * src_channels;
retval->src_format = src_format;
retval->src_channels = src_channels;
retval->src_rate = src_rate;
retval->src_sample_frame_size = (SDL_AUDIO_BITSIZE(src_spec->format) / 8) * src_spec->channels;
retval->packetlen = packetlen;
SDL_memcpy(&retval->src_spec, src_spec, sizeof (SDL_AudioSpec));
if (SetAudioStreamFormat(retval, src_format, src_channels, src_rate, dst_format, dst_channels, dst_rate) == -1) {
if (SetAudioStreamFormat(retval, src_spec, dst_spec) == -1) {
SDL_DestroyAudioStream(retval);
return NULL;
}
@ -663,50 +671,56 @@ int SDL_UnlockAudioStream(SDL_AudioStream *stream)
return stream ? SDL_UnlockMutex(stream->lock) : SDL_InvalidParamError("stream");
}
int SDL_GetAudioStreamFormat(SDL_AudioStream *stream, SDL_AudioFormat *src_format, int *src_channels, int *src_rate, SDL_AudioFormat *dst_format, int *dst_channels, int *dst_rate)
int SDL_GetAudioStreamFormat(SDL_AudioStream *stream, SDL_AudioSpec *src_spec, SDL_AudioSpec *dst_spec)
{
if (!stream) {
return SDL_InvalidParamError("stream");
}
SDL_LockMutex(stream->lock);
#define GETAUDIOSTREAMFIELD(x) if (x) { *x = stream->x; }
GETAUDIOSTREAMFIELD(src_format);
GETAUDIOSTREAMFIELD(src_channels);
GETAUDIOSTREAMFIELD(src_rate);
GETAUDIOSTREAMFIELD(dst_format);
GETAUDIOSTREAMFIELD(dst_channels);
GETAUDIOSTREAMFIELD(dst_rate);
#undef GETAUDIOSTREAMFIELD
if (src_spec) {
SDL_memcpy(src_spec, &stream->src_spec, sizeof (SDL_AudioSpec));
}
if (dst_spec) {
SDL_memcpy(dst_spec, &stream->dst_spec, sizeof (SDL_AudioSpec));
}
SDL_UnlockMutex(stream->lock);
return 0;
}
int SDL_SetAudioStreamFormat(SDL_AudioStream *stream, SDL_AudioFormat src_format, int src_channels, int src_rate, SDL_AudioFormat dst_format, int dst_channels, int dst_rate)
int SDL_SetAudioStreamFormat(SDL_AudioStream *stream, const SDL_AudioSpec *src_spec, const SDL_AudioSpec *dst_spec)
{
int retval;
if (!stream) {
return SDL_InvalidParamError("stream");
} else if (!SDL_IsSupportedAudioFormat(src_format)) {
return SDL_InvalidParamError("src_format");
} else if (!SDL_IsSupportedChannelCount(src_channels)) {
return SDL_InvalidParamError("src_channels");
} else if (src_rate <= 0) {
return SDL_InvalidParamError("src_rate");
} else if (src_rate >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
return SDL_SetError("Source rate is too high");
} else if (!SDL_IsSupportedAudioFormat(dst_format)) {
return SDL_InvalidParamError("dst_format");
} else if (!SDL_IsSupportedChannelCount(dst_channels)) {
return SDL_InvalidParamError("dst_channels");
} else if (dst_rate <= 0) {
return SDL_InvalidParamError("dst_rate");
} else if (dst_rate >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
return SDL_SetError("Destination rate is too high");
}
if (src_spec) {
if (!SDL_IsSupportedAudioFormat(src_spec->format)) {
return SDL_InvalidParamError("src_spec->format");
} else if (!SDL_IsSupportedChannelCount(src_spec->channels)) {
return SDL_InvalidParamError("src_spec->channels");
} else if (src_spec->freq <= 0) {
return SDL_InvalidParamError("src_spec->freq");
} else if (src_spec->freq >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
return SDL_SetError("Source rate is too high");
}
}
if (dst_spec) {
if (!SDL_IsSupportedAudioFormat(dst_spec->format)) {
return SDL_InvalidParamError("dst_spec->format");
} else if (!SDL_IsSupportedChannelCount(dst_spec->channels)) {
return SDL_InvalidParamError("dst_spec->channels");
} else if (dst_spec->freq <= 0) {
return SDL_InvalidParamError("dst_spec->freq");
} else if (dst_spec->freq >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
return SDL_SetError("Destination rate is too high");
}
}
SDL_LockMutex(stream->lock);
retval = SetAudioStreamFormat(stream, src_format, src_channels, src_rate, dst_format, dst_channels, dst_rate);
retval = SetAudioStreamFormat(stream, src_spec ? src_spec : &stream->src_spec, dst_spec ? dst_spec : &stream->dst_spec);
SDL_UnlockMutex(stream->lock);
return retval;
@ -797,9 +811,9 @@ static int CalculateAudioStreamWorkBufSize(const SDL_AudioStream *stream, int le
workbuflen = inputlen;
}
if (stream->dst_rate != stream->src_rate) {
if (stream->dst_spec.freq != stream->src_spec.freq) {
/* calculate requested sample frames needed before resampling. Use a Uint64 so the multiplication doesn't overflow. */
const int input_frames = ((int) ((((Uint64) workbuf_frames) * stream->src_rate) / stream->dst_rate));
const int input_frames = ((int) ((((Uint64) workbuf_frames) * stream->src_spec.freq) / stream->dst_spec.freq));
inputlen = input_frames * stream->max_sample_frame_size;
if (inputlen > workbuflen) {
workbuflen = inputlen;
@ -820,13 +834,13 @@ static int CalculateAudioStreamWorkBufSize(const SDL_AudioStream *stream, int le
static int GetAudioStreamDataInternal(SDL_AudioStream *stream, void *buf, int len)
{
const int max_available = SDL_GetAudioStreamAvailable(stream);
const SDL_AudioFormat src_format = stream->src_format;
const int src_channels = stream->src_channels;
const int src_rate = stream->src_rate;
const SDL_AudioFormat src_format = stream->src_spec.format;
const int src_channels = stream->src_spec.channels;
const int src_rate = stream->src_spec.freq;
const int src_sample_frame_size = stream->src_sample_frame_size;
const SDL_AudioFormat dst_format = stream->dst_format;
const int dst_channels = stream->dst_channels;
const int dst_rate = stream->dst_rate;
const SDL_AudioFormat dst_format = stream->dst_spec.format;
const int dst_channels = stream->dst_spec.channels;
const int dst_rate = stream->dst_spec.freq;
const int dst_sample_frame_size = stream->dst_sample_frame_size;
const int max_sample_frame_size = stream->max_sample_frame_size;
const int pre_resample_channels = stream->pre_resample_channels;
@ -1022,9 +1036,9 @@ int SDL_GetAudioStreamData(SDL_AudioStream *stream, void *voidbuf, int len)
// give the callback a chance to fill in more stream data if it wants.
if (stream->get_callback) {
int approx_request = len / stream->dst_sample_frame_size; /* start with sample frames desired */
if (stream->src_rate != stream->dst_rate) {
if (stream->src_spec.freq != stream->dst_spec.freq) {
/* calculate difference in dataset size after resampling. Use a Uint64 so the multiplication doesn't overflow. */
approx_request = (size_t) ((((Uint64) approx_request) * stream->src_rate) / stream->dst_rate);
approx_request = (size_t) ((((Uint64) approx_request) * stream->src_spec.freq) / stream->dst_spec.freq);
if (!stream->flushed) { /* do we need to fill the future buffer to accomodate this, too? */
approx_request += stream->future_buffer_filled_frames - stream->resampler_padding_frames;
}
@ -1091,13 +1105,13 @@ int SDL_GetAudioStreamAvailable(SDL_AudioStream *stream)
count += stream->future_buffer_filled_frames;
/* sample frames after resampling */
if (stream->src_rate != stream->dst_rate) {
if (stream->src_spec.freq != stream->dst_spec.freq) {
if (!stream->flushed) {
/* have to save some samples for padding. They aren't available until more data is added or the stream is flushed. */
count = (count < ((size_t) stream->resampler_padding_frames)) ? 0 : (count - stream->resampler_padding_frames);
}
/* calculate difference in dataset size after resampling. Use a Uint64 so the multiplication doesn't overflow. */
count = (size_t) ((((Uint64) count) * stream->dst_rate) / stream->src_rate);
count = (size_t) ((((Uint64) count) * stream->dst_spec.freq) / stream->src_spec.freq);
}
/* convert from sample frames to bytes in destination format. */
@ -1117,7 +1131,7 @@ int SDL_ClearAudioStream(SDL_AudioStream *stream)
SDL_LockMutex(stream->lock);
SDL_ClearDataQueue(stream->queue, (size_t)stream->packetlen * 2);
SDL_memset(stream->history_buffer, SDL_GetSilenceValueForFormat(stream->src_format), stream->history_buffer_frames * stream->src_channels * sizeof (float));
SDL_memset(stream->history_buffer, SDL_GetSilenceValueForFormat(stream->src_spec.format), stream->history_buffer_frames * stream->src_spec.channels * sizeof (float));
stream->future_buffer_filled_frames = 0;
stream->flushed = SDL_FALSE;
SDL_UnlockMutex(stream->lock);
@ -1139,8 +1153,8 @@ void SDL_DestroyAudioStream(SDL_AudioStream *stream)
}
}
int SDL_ConvertAudioSamples(SDL_AudioFormat src_format, int src_channels, int src_rate, const Uint8 *src_data, int src_len,
SDL_AudioFormat dst_format, int dst_channels, int dst_rate, Uint8 **dst_data, int *dst_len)
int SDL_ConvertAudioSamples(const SDL_AudioSpec *src_spec, const Uint8 *src_data, int src_len,
const SDL_AudioSpec *dst_spec, Uint8 **dst_data, int *dst_len)
{
int ret = -1;
SDL_AudioStream *stream = NULL;
@ -1165,7 +1179,7 @@ int SDL_ConvertAudioSamples(SDL_AudioFormat src_format, int src_channels, int sr
return SDL_InvalidParamError("dst_len");
}
stream = SDL_CreateAudioStream(src_format, src_channels, src_rate, dst_format, dst_channels, dst_rate);
stream = SDL_CreateAudioStream(src_spec, dst_spec);
if (stream != NULL) {
if ((SDL_PutAudioStreamData(stream, src_data, src_len) == 0) && (SDL_FlushAudioStream(stream) == 0)) {
dstlen = SDL_GetAudioStreamAvailable(stream);

View File

@ -73,7 +73,7 @@ extern void SDL_ChooseAudioConverters(void);
/* Audio targets should call this as devices are added to the system (such as
a USB headset being plugged in), and should also be called for
for every device found during DetectDevices(). */
extern SDL_AudioDevice *SDL_AddAudioDevice(const SDL_bool iscapture, const char *name, SDL_AudioFormat fmt, int channels, int freq, void *handle);
extern SDL_AudioDevice *SDL_AddAudioDevice(const SDL_bool iscapture, const char *name, const SDL_AudioSpec *spec, void *handle);
/* Audio targets should call this if an opened audio device is lost.
This can happen due to i/o errors, or a device being unplugged, etc. */
@ -159,17 +159,12 @@ struct SDL_AudioStream
int history_buffer_frames;
int future_buffer_filled_frames;
int max_sample_frame_size;
SDL_AudioSpec src_spec;
SDL_AudioSpec dst_spec;
int src_sample_frame_size;
SDL_AudioFormat src_format;
int src_channels;
int src_rate;
int dst_sample_frame_size;
SDL_AudioFormat dst_format;
int dst_channels;
int dst_rate;
int max_sample_frame_size;
int pre_resample_channels;
int packetlen;
@ -194,15 +189,11 @@ struct SDL_AudioDevice
void *handle;
/* The device's current audio specification */
SDL_AudioFormat format;
int freq;
int channels;
SDL_AudioSpec spec;
Uint32 buffer_size;
/* The device's default audio specification */
SDL_AudioFormat default_format;
int default_freq;
int default_channels;
SDL_AudioSpec default_spec;
/* Number of sample frames the devices wants per-buffer. */
int sample_frames;

View File

@ -1764,7 +1764,7 @@ static int WaveCheckFormat(WaveFile *file, size_t datalength)
return 0;
}
static int WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioFormat *fmt, int *channels, int *freq, Uint8 **audio_buf, Uint32 *audio_len)
static int WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
{
int result;
Uint32 chunkcount = 0;
@ -2026,8 +2026,9 @@ static int WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioFormat *fmt, int *c
/* Setting up the specs. All unsupported formats were filtered out
* by checks earlier in this function.
*/
*freq = format->frequency;
*channels = (Uint8)format->channels;
spec->freq = format->frequency;
spec->channels = (Uint8)format->channels;
spec->format = 0;
switch (format->encoding) {
case MS_ADPCM_CODE:
@ -2035,22 +2036,22 @@ static int WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioFormat *fmt, int *c
case ALAW_CODE:
case MULAW_CODE:
/* These can be easily stored in the byte order of the system. */
*fmt = SDL_AUDIO_S16SYS;
spec->format = SDL_AUDIO_S16SYS;
break;
case IEEE_FLOAT_CODE:
*fmt = SDL_AUDIO_F32LSB;
spec->format = SDL_AUDIO_F32LSB;
break;
case PCM_CODE:
switch (format->bitspersample) {
case 8:
*fmt = SDL_AUDIO_U8;
spec->format = SDL_AUDIO_U8;
break;
case 16:
*fmt = SDL_AUDIO_S16LSB;
spec->format = SDL_AUDIO_S16LSB;
break;
case 24: /* Has been shifted to 32 bits. */
case 32:
*fmt = SDL_AUDIO_S32LSB;
spec->format = SDL_AUDIO_S32LSB;
break;
default:
/* Just in case something unexpected happened in the checks. */
@ -2069,7 +2070,7 @@ static int WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioFormat *fmt, int *c
return 0;
}
int SDL_LoadWAV_RW(SDL_RWops *src, int freesrc, SDL_AudioFormat *fmt, int *channels, int *freq, Uint8 **audio_buf, Uint32 *audio_len)
int SDL_LoadWAV_RW(SDL_RWops *src, int freesrc, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
{
int result = -1;
WaveFile file;
@ -2077,12 +2078,8 @@ int SDL_LoadWAV_RW(SDL_RWops *src, int freesrc, SDL_AudioFormat *fmt, int *chann
/* Make sure we are passed a valid data source */
if (src == NULL) {
return -1; /* Error may come from RWops. */
} else if (fmt == NULL) {
return SDL_InvalidParamError("fmt");
} else if (channels == NULL) {
return SDL_InvalidParamError("channels");
} else if (freq == NULL) {
return SDL_InvalidParamError("freq");
} else if (spec == NULL) {
return SDL_InvalidParamError("spec");
} else if (audio_buf == NULL) {
return SDL_InvalidParamError("audio_buf");
} else if (audio_len == NULL) {
@ -2097,7 +2094,7 @@ int SDL_LoadWAV_RW(SDL_RWops *src, int freesrc, SDL_AudioFormat *fmt, int *chann
file.trunchint = WaveGetTruncationHint();
file.facthint = WaveGetFactChunkHint();
result = WaveLoad(src, &file, fmt, channels, freq, audio_buf, audio_len);
result = WaveLoad(src, &file, spec, audio_buf, audio_len);
if (result < 0) {
SDL_free(*audio_buf);
audio_buf = NULL;

View File

@ -123,7 +123,7 @@ static int DISKAUDIO_OpenDevice(SDL_AudioDevice *device)
if (envr != NULL) {
device->hidden->io_delay = SDL_atoi(envr);
} else {
device->hidden->io_delay = ((device->sample_frames * 1000) / device->freq);
device->hidden->io_delay = ((device->sample_frames * 1000) / device->spec.freq);
}
/* Open the "audio device" */
@ -153,8 +153,8 @@ static int DISKAUDIO_OpenDevice(SDL_AudioDevice *device)
static void DISKAUDIO_DetectDevices(void)
{
SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, 0, 0, 0, (void *)0x1);
SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, 0, 0, 0, (void *)0x2);
SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, NULL, (void *)0x1);
SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, NULL, (void *)0x2);
}
static SDL_bool DISKAUDIO_Init(SDL_AudioDriverImpl *impl)

View File

@ -50,7 +50,7 @@ static Uint8 *DUMMYAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
static int DUMMYAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen)
{
/* Delay to make this sort of simulate real audio input. */
SDL_Delay((device->sample_frames * 1000) / device->freq);
SDL_Delay((device->sample_frames * 1000) / device->spec.freq);
/* always return a full buffer of silence. */
SDL_memset(buffer, device->silence_value, buflen);

View File

@ -599,7 +599,7 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
SDL_zerop(device->hidden);
/* Try for a closest match on audio format */
closefmts = SDL_ClosestAudioFormats(device->format);
closefmts = SDL_ClosestAudioFormats(device->spec.format);
while ((test_format = *(closefmts++)) != 0) {
#ifdef DEBUG_AUDIO
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
@ -634,7 +634,7 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
if (!test_format) {
return SDL_SetError("pulseaudio: Unsupported audio format");
}
device->format = test_format;
device->spec.format = test_format;
paspec.format = format;
/* Calculate the final parameters for this audio specification */
@ -650,8 +650,8 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
SDL_memset(h->mixbuf, device->silence_value, device->buffer_size);
}
paspec.channels = device->channels;
paspec.rate = device->freq;
paspec.channels = device->spec.channels;
paspec.rate = device->spec.freq;
/* Reduced prebuffering compared to the defaults. */
paattr.fragsize = device->buffer_size;
@ -669,7 +669,7 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
const char *name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME);
/* The SDL ALSA output hints us that we use Windows' channel mapping */
/* https://bugzilla.libsdl.org/show_bug.cgi?id=110 */
PULSEAUDIO_pa_channel_map_init_auto(&pacmap, device->channels, PA_CHANNEL_MAP_WAVEEX);
PULSEAUDIO_pa_channel_map_init_auto(&pacmap, device->spec.channels, PA_CHANNEL_MAP_WAVEEX);
h->stream = PULSEAUDIO_pa_stream_new(
pulseaudio_context,
@ -750,12 +750,13 @@ static void SinkInfoCallback(pa_context *c, const pa_sink_info *i, int is_last,
{
if (i) {
const SDL_bool add = (SDL_bool)((intptr_t)data);
const SDL_AudioFormat fmt = PulseFormatToSDLFormat(i->sample_spec.format);
const int channels = i->sample_spec.channels;
const int freq = i->sample_spec.rate;
SDL_AudioSpec spec;
spec.format = PulseFormatToSDLFormat(i->sample_spec.format);
spec.channels = i->sample_spec.channels;
spec.freq = i->sample_spec.rate;
if (add) {
SDL_AddAudioDevice(SDL_FALSE, i->description, fmt, channels, freq, (void *)((intptr_t)i->index + 1));
SDL_AddAudioDevice(SDL_FALSE, i->description, &spec, (void *)((intptr_t)i->index + 1));
}
if (default_sink_path != NULL && SDL_strcmp(i->name, default_sink_path) == 0) {
@ -772,12 +773,13 @@ static void SourceInfoCallback(pa_context *c, const pa_source_info *i, int is_la
/* Maybe skip "monitor" sources. These are just output from other sinks. */
if (i && (include_monitors || (i->monitor_of_sink == PA_INVALID_INDEX))) {
const SDL_bool add = (SDL_bool)((intptr_t)data);
const SDL_AudioFormat fmt = PulseFormatToSDLFormat(i->sample_spec.format);
const int channels = i->sample_spec.channels;
const int freq = i->sample_spec.rate;
SDL_AudioSpec spec;
spec.format = PulseFormatToSDLFormat(i->sample_spec.format);
spec.channels = i->sample_spec.channels;
spec.freq = i->sample_spec.rate;
if (add) {
SDL_AddAudioDevice(SDL_TRUE, i->description, fmt, channels, freq, (void *)((intptr_t)i->index + 1));
SDL_AddAudioDevice(SDL_TRUE, i->description, &spec, (void *)((intptr_t)i->index + 1));
}
if (default_source_path != NULL && SDL_strcmp(i->name, default_source_path) == 0) {

View File

@ -929,28 +929,28 @@ SDL_DYNAPI_PROC(const char*,SDL_GetCurrentAudioDriver,(void),(),return)
SDL_DYNAPI_PROC(SDL_AudioDeviceID*,SDL_GetAudioOutputDevices,(int *a),(a),return)
SDL_DYNAPI_PROC(SDL_AudioDeviceID*,SDL_GetAudioCaptureDevices,(int *a),(a),return)
SDL_DYNAPI_PROC(char*,SDL_GetAudioDeviceName,(SDL_AudioDeviceID a),(a),return)
SDL_DYNAPI_PROC(int,SDL_GetAudioDeviceFormat,(SDL_AudioDeviceID a, SDL_AudioFormat *b, int *c, int *d),(a,b,c,d),return)
SDL_DYNAPI_PROC(SDL_AudioDeviceID,SDL_OpenAudioDevice,(SDL_AudioDeviceID a, SDL_AudioFormat b, int c, int d),(a,b,c,d),return)
SDL_DYNAPI_PROC(int,SDL_GetAudioDeviceFormat,(SDL_AudioDeviceID a, SDL_AudioSpec *b),(a,b),return)
SDL_DYNAPI_PROC(SDL_AudioDeviceID,SDL_OpenAudioDevice,(SDL_AudioDeviceID a, const SDL_AudioSpec *b),(a,b),return)
SDL_DYNAPI_PROC(void,SDL_CloseAudioDevice,(SDL_AudioDeviceID a),(a),)
SDL_DYNAPI_PROC(int,SDL_BindAudioStreams,(SDL_AudioDeviceID a, SDL_AudioStream **b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_BindAudioStream,(SDL_AudioDeviceID a, SDL_AudioStream *b),(a,b),return)
SDL_DYNAPI_PROC(void,SDL_UnbindAudioStreams,(SDL_AudioStream **a, int b),(a,b),)
SDL_DYNAPI_PROC(void,SDL_UnbindAudioStream,(SDL_AudioStream *a),(a),)
SDL_DYNAPI_PROC(SDL_AudioStream*,SDL_CreateAudioStream,(SDL_AudioFormat a, int b, int c, SDL_AudioFormat d, int e, int f),(a,b,c,d,e,f),return)
SDL_DYNAPI_PROC(int,SDL_GetAudioStreamFormat,(SDL_AudioStream *a, SDL_AudioFormat *b, int *c, int *d, SDL_AudioFormat *e, int *f, int *g),(a,b,c,d,e,f,g),return)
SDL_DYNAPI_PROC(int,SDL_SetAudioStreamFormat,(SDL_AudioStream *a, SDL_AudioFormat b, int c, int d, SDL_AudioFormat e, int f, int g),(a,b,c,d,e,f,g),return)
SDL_DYNAPI_PROC(SDL_AudioStream*,SDL_CreateAudioStream,(const SDL_AudioSpec *a, const SDL_AudioSpec *b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_GetAudioStreamFormat,(SDL_AudioStream *a, SDL_AudioSpec *b, SDL_AudioSpec *c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_SetAudioStreamFormat,(SDL_AudioStream *a, const SDL_AudioSpec *b, const SDL_AudioSpec *c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_PutAudioStreamData,(SDL_AudioStream *a, const void *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_GetAudioStreamData,(SDL_AudioStream *a, void *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_GetAudioStreamAvailable,(SDL_AudioStream *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_FlushAudioStream,(SDL_AudioStream *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_ClearAudioStream,(SDL_AudioStream *a),(a),return)
SDL_DYNAPI_PROC(void,SDL_DestroyAudioStream,(SDL_AudioStream *a),(a),)
SDL_DYNAPI_PROC(SDL_AudioStream*,SDL_CreateAndBindAudioStream,(SDL_AudioDeviceID a, SDL_AudioFormat b, int c, int d),(a,b,c,d),return)
SDL_DYNAPI_PROC(int,SDL_LoadWAV_RW,(SDL_RWops *a, int b, SDL_AudioFormat *c, int *d, int *e, Uint8 **f, Uint32 *g),(a,b,c,d,e,f,g),return)
SDL_DYNAPI_PROC(int,SDL_MixAudioFormat,(Uint8 *a, const Uint8 *b, SDL_AudioFormat c, Uint32 d, int e),(a,b,c,d,e),return)
SDL_DYNAPI_PROC(int,SDL_ConvertAudioSamples,(SDL_AudioFormat a, int b, int c, const Uint8 *d, int e, SDL_AudioFormat f, int g, int h, Uint8 **i, int *j),(a,b,c,d,e,f,g,h,i,j),return)
SDL_DYNAPI_PROC(int,SDL_GetSilenceValueForFormat,(SDL_AudioFormat a),(a),return)
SDL_DYNAPI_PROC(int,SDL_LockAudioStream,(SDL_AudioStream *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_UnlockAudioStream,(SDL_AudioStream *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_SetAudioStreamGetCallback,(SDL_AudioStream *a, SDL_AudioStreamRequestCallback b, void *c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_SetAudioStreamPutCallback,(SDL_AudioStream *a, SDL_AudioStreamRequestCallback b, void *c),(a,b,c),return)
SDL_DYNAPI_PROC(void,SDL_DestroyAudioStream,(SDL_AudioStream *a),(a),)
SDL_DYNAPI_PROC(SDL_AudioStream*,SDL_CreateAndBindAudioStream,(SDL_AudioDeviceID a, const SDL_AudioSpec *b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_LoadWAV_RW,(SDL_RWops *a, int b, SDL_AudioSpec *c, Uint8 **d, Uint32 *e),(a,b,c,d,e),return)
SDL_DYNAPI_PROC(int,SDL_MixAudioFormat,(Uint8 *a, const Uint8 *b, SDL_AudioFormat c, Uint32 d, int e),(a,b,c,d,e),return)
SDL_DYNAPI_PROC(int,SDL_ConvertAudioSamples,(const SDL_AudioSpec *a, const Uint8 *b, int c, const SDL_AudioSpec *d, Uint8 **e, int *f),(a,b,c,d,e,f),return)
SDL_DYNAPI_PROC(int,SDL_GetSilenceValueForFormat,(SDL_AudioFormat a),(a),return)

View File

@ -1443,7 +1443,8 @@ SDL_bool SDLTest_CommonInit(SDLTest_CommonState *state)
SDL_GetCurrentAudioDriver());
}
state->audio_id = SDL_OpenAudioDevice(0, state->audio_format, state->audio_channels, state->audio_freq);
const SDL_AudioSpec spec = { state->audio_format, state->audio_channels, state->audio_freq };
state->audio_id = SDL_OpenAudioDevice(0, &spec);
if (!state->audio_id) {
SDL_Log("Couldn't open audio: %s\n", SDL_GetError());
return SDL_FALSE;

View File

@ -28,9 +28,7 @@
static struct
{
SDL_AudioFormat fmt;
int channels;
int freq;
SDL_AudioSpec spec;
Uint8 *sound; /* Pointer to wave data */
Uint32 soundlen; /* Length of wave data */
Uint32 soundpos;
@ -89,14 +87,14 @@ static void
open_audio(void)
{
SDL_AudioDeviceID *devices = SDL_GetAudioOutputDevices(NULL);
device = devices ? SDL_OpenAudioDevice(devices[0], wave.fmt, wave.channels, wave.freq) : 0;
device = devices ? SDL_OpenAudioDevice(devices[0], &wave.spec) : 0;
SDL_free(devices);
if (!device) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open audio: %s\n", SDL_GetError());
SDL_free(wave.sound);
quit(2);
}
stream = SDL_CreateAndBindAudioStream(device, wave.fmt, wave.channels, wave.freq);
stream = SDL_CreateAndBindAudioStream(device, &wave.spec);
if (!stream) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create audio stream: %s\n", SDL_GetError());
SDL_CloseAudioDevice(device);
@ -180,7 +178,7 @@ int main(int argc, char *argv[])
}
/* Load the wave file into memory */
if (SDL_LoadWAV(filename, &wave.fmt, &wave.channels, &wave.freq, &wave.sound, &wave.soundlen) == -1) {
if (SDL_LoadWAV(filename, &wave.spec, &wave.sound, &wave.soundlen) == -1) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", filename, SDL_GetError());
quit(1);
}