mirror of https://github.com/libsdl-org/SDL
audio: Allow querying of device buffer size.
This commit is contained in:
parent
cf95721130
commit
2f43f7bc53
|
@ -327,8 +327,20 @@ extern DECLSPEC char *SDLCALL SDL_GetAudioDeviceName(SDL_AudioDeviceID devid);
|
|||
* reasonable recommendation before opening the system-recommended default
|
||||
* device.
|
||||
*
|
||||
* You can also use this to request the current device buffer size. This is
|
||||
* specified in sample frames and represents the amount of data SDL will
|
||||
* feed to the physical hardware in each chunk. This can be converted to
|
||||
* milliseconds of audio with the following equation:
|
||||
*
|
||||
* `ms = (int) ((((Sint64) frames) * 1000) / spec.freq);`
|
||||
*
|
||||
* Buffer size is only important if you need low-level control over the audio
|
||||
* playback timing. Most apps do not need this.
|
||||
*
|
||||
* \param devid the instance ID of the device to query.
|
||||
* \param spec On return, will be filled with device details.
|
||||
* \param sample_frames Pointer to store device buffer size, in sample frames.
|
||||
* Can be NULL.
|
||||
* \returns 0 on success or a negative error code on failure; call
|
||||
* SDL_GetError() for more information.
|
||||
*
|
||||
|
@ -336,7 +348,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_AudioSpec *spec);
|
||||
extern DECLSPEC int SDLCALL SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec, int *sample_frames);
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -116,6 +116,30 @@ const char *SDL_GetCurrentAudioDriver(void)
|
|||
return current_audio.name;
|
||||
}
|
||||
|
||||
static int GetDefaultSampleFramesFromFreq(const int freq)
|
||||
{
|
||||
const char *hint = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES);
|
||||
if (hint) {
|
||||
const int val = SDL_atoi(hint);
|
||||
if (val > 0) {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
if (freq <= 11025) {
|
||||
return 512;
|
||||
} else if (freq <= 22050) {
|
||||
return 1024;
|
||||
} else if (freq <= 48000) {
|
||||
return 2048;
|
||||
} else if (freq <= 96000) {
|
||||
return 4096;
|
||||
}
|
||||
|
||||
return 8192; // shrug
|
||||
}
|
||||
|
||||
|
||||
// device management and hotplug...
|
||||
|
||||
|
||||
|
@ -238,6 +262,7 @@ static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool isc
|
|||
device->iscapture = iscapture;
|
||||
SDL_memcpy(&device->spec, spec, sizeof (SDL_AudioSpec));
|
||||
SDL_memcpy(&device->default_spec, spec, sizeof (SDL_AudioSpec));
|
||||
device->sample_frames = GetDefaultSampleFramesFromFreq(device->spec.freq);
|
||||
device->silence_value = SDL_GetSilenceValueForFormat(device->spec.format);
|
||||
device->handle = handle;
|
||||
device->prev = NULL;
|
||||
|
@ -1112,7 +1137,7 @@ char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid)
|
|||
return retval;
|
||||
}
|
||||
|
||||
int SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec)
|
||||
int SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec, int *sample_frames)
|
||||
{
|
||||
if (!spec) {
|
||||
return SDL_InvalidParamError("spec");
|
||||
|
@ -1137,6 +1162,9 @@ int SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec)
|
|||
}
|
||||
|
||||
SDL_memcpy(spec, &device->spec, sizeof (SDL_AudioSpec));
|
||||
if (sample_frames) {
|
||||
*sample_frames = device->sample_frames;
|
||||
}
|
||||
SDL_UnlockMutex(device->lock);
|
||||
|
||||
return 0;
|
||||
|
@ -1246,29 +1274,6 @@ static void PrepareAudioFormat(SDL_bool iscapture, SDL_AudioSpec *spec)
|
|||
}
|
||||
}
|
||||
|
||||
static int GetDefaultSampleFramesFromFreq(const int freq)
|
||||
{
|
||||
const char *hint = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES);
|
||||
if (hint) {
|
||||
const int val = SDL_atoi(hint);
|
||||
if (val > 0) {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
if (freq <= 11025) {
|
||||
return 512;
|
||||
} else if (freq <= 22050) {
|
||||
return 1024;
|
||||
} else if (freq <= 48000) {
|
||||
return 2048;
|
||||
} else if (freq <= 96000) {
|
||||
return 4096;
|
||||
}
|
||||
|
||||
return 8192; // shrug
|
||||
}
|
||||
|
||||
void SDL_UpdatedAudioDeviceFormat(SDL_AudioDevice *device)
|
||||
{
|
||||
device->silence_value = SDL_GetSilenceValueForFormat(device->spec.format);
|
||||
|
|
|
@ -926,7 +926,7 @@ 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_AudioSpec *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_GetAudioDeviceFormat,(SDL_AudioDeviceID a, SDL_AudioSpec *b, int *c),(a,b,c),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)
|
||||
|
|
|
@ -765,9 +765,10 @@ static void DeviceThing_ondrag(Thing *thing, int button, float x, float y)
|
|||
static void SetLogicalDeviceTitlebar(Thing *thing)
|
||||
{
|
||||
SDL_AudioSpec *spec = &thing->data.logdev.spec;
|
||||
SDL_GetAudioDeviceFormat(thing->data.logdev.devid, spec);
|
||||
int frames = 0;
|
||||
SDL_GetAudioDeviceFormat(thing->data.logdev.devid, spec, &frames);
|
||||
SDL_free(thing->titlebar);
|
||||
SDL_asprintf(&thing->titlebar, "Logical device #%u (%s, %s, %s, %uHz)", (unsigned int) thing->data.logdev.devid, thing->data.logdev.iscapture ? "CAPTURE" : "OUTPUT", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq);
|
||||
SDL_asprintf(&thing->titlebar, "Logical device #%u (%s, %s, %s, %uHz, %d frames)", (unsigned int) thing->data.logdev.devid, thing->data.logdev.iscapture ? "CAPTURE" : "OUTPUT", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq, frames);
|
||||
}
|
||||
|
||||
static void LogicalDeviceThing_ondrop(Thing *thing, int button, float x, float y)
|
||||
|
@ -938,15 +939,16 @@ static Thing *CreateLogicalDeviceThing(Thing *parent, const SDL_AudioDeviceID wh
|
|||
|
||||
static void SetPhysicalDeviceTitlebar(Thing *thing)
|
||||
{
|
||||
int frames = 0;
|
||||
SDL_AudioSpec *spec = &thing->data.physdev.spec;
|
||||
SDL_GetAudioDeviceFormat(thing->data.physdev.devid, spec);
|
||||
SDL_GetAudioDeviceFormat(thing->data.physdev.devid, spec, &frames);
|
||||
SDL_free(thing->titlebar);
|
||||
if (thing->data.physdev.devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE) {
|
||||
SDL_asprintf(&thing->titlebar, "Default system device (CAPTURE, %s, %s, %uHz)", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq);
|
||||
SDL_asprintf(&thing->titlebar, "Default system device (CAPTURE, %s, %s, %uHz, %d frames)", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq, frames);
|
||||
} else if (thing->data.physdev.devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) {
|
||||
SDL_asprintf(&thing->titlebar, "Default system device (OUTPUT, %s, %s, %uHz)", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq);
|
||||
SDL_asprintf(&thing->titlebar, "Default system device (OUTPUT, %s, %s, %uHz, %d frames)", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq, frames);
|
||||
} else {
|
||||
SDL_asprintf(&thing->titlebar, "Physical device #%u (%s, \"%s\", %s, %s, %uHz)", (unsigned int) thing->data.physdev.devid, thing->data.physdev.iscapture ? "CAPTURE" : "OUTPUT", thing->data.physdev.name, AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq);
|
||||
SDL_asprintf(&thing->titlebar, "Physical device #%u (%s, \"%s\", %s, %s, %uHz, %d frames)", (unsigned int) thing->data.physdev.devid, thing->data.physdev.iscapture ? "CAPTURE" : "OUTPUT", thing->data.physdev.name, AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq, frames);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -179,7 +179,7 @@ int main(int argc, char **argv)
|
|||
exit(1);
|
||||
}
|
||||
SDL_PauseAudioDevice(device);
|
||||
SDL_GetAudioDeviceFormat(device, &outspec);
|
||||
SDL_GetAudioDeviceFormat(device, &outspec, NULL);
|
||||
stream_out = SDL_CreateAudioStream(&outspec, &outspec);
|
||||
if (!stream_out) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create an audio stream for playback: %s!\n", SDL_GetError());
|
||||
|
@ -203,7 +203,7 @@ int main(int argc, char **argv)
|
|||
exit(1);
|
||||
}
|
||||
SDL_PauseAudioDevice(device);
|
||||
SDL_GetAudioDeviceFormat(device, &inspec);
|
||||
SDL_GetAudioDeviceFormat(device, &inspec, NULL);
|
||||
stream_in = SDL_CreateAudioStream(&inspec, &inspec);
|
||||
if (!stream_in) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create an audio stream for capture: %s!\n", SDL_GetError());
|
||||
|
|
|
@ -19,6 +19,7 @@ print_devices(SDL_bool iscapture)
|
|||
SDL_AudioSpec spec;
|
||||
const char *typestr = ((iscapture) ? "capture" : "output");
|
||||
int n = 0;
|
||||
int frames;
|
||||
SDL_AudioDeviceID *devices = iscapture ? SDL_GetAudioCaptureDevices(&n) : SDL_GetAudioOutputDevices(&n);
|
||||
|
||||
if (devices == NULL) {
|
||||
|
@ -37,10 +38,11 @@ print_devices(SDL_bool iscapture)
|
|||
SDL_Log(" %d Error: %s\n", i, SDL_GetError());
|
||||
}
|
||||
|
||||
if (SDL_GetAudioDeviceFormat(devices[i], &spec) == 0) {
|
||||
if (SDL_GetAudioDeviceFormat(devices[i], &spec, &frames) == 0) {
|
||||
SDL_Log(" Sample Rate: %d\n", spec.freq);
|
||||
SDL_Log(" Channels: %d\n", spec.channels);
|
||||
SDL_Log(" SDL_AudioFormat: %X\n", spec.format);
|
||||
SDL_Log(" Buffer Size: %d frames\n", frames);
|
||||
}
|
||||
}
|
||||
SDL_Log("\n");
|
||||
|
@ -53,6 +55,7 @@ int main(int argc, char **argv)
|
|||
SDL_AudioSpec spec;
|
||||
int i;
|
||||
int n;
|
||||
int frames;
|
||||
SDLTest_CommonState *state;
|
||||
|
||||
/* Initialize test framework */
|
||||
|
@ -92,22 +95,24 @@ int main(int argc, char **argv)
|
|||
print_devices(SDL_FALSE);
|
||||
print_devices(SDL_TRUE);
|
||||
|
||||
if (SDL_GetAudioDeviceFormat(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec) < 0) {
|
||||
if (SDL_GetAudioDeviceFormat(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec, &frames) < 0) {
|
||||
SDL_Log("Error when calling SDL_GetAudioDeviceFormat(default output): %s\n", SDL_GetError());
|
||||
} else {
|
||||
SDL_Log("Default Output Device:\n");
|
||||
SDL_Log("Sample Rate: %d\n", spec.freq);
|
||||
SDL_Log("Channels: %d\n", spec.channels);
|
||||
SDL_Log("SDL_AudioFormat: %X\n", spec.format);
|
||||
SDL_Log("Buffer Size: %d frames\n", frames);
|
||||
}
|
||||
|
||||
if (SDL_GetAudioDeviceFormat(SDL_AUDIO_DEVICE_DEFAULT_CAPTURE, &spec) < 0) {
|
||||
if (SDL_GetAudioDeviceFormat(SDL_AUDIO_DEVICE_DEFAULT_CAPTURE, &spec, &frames) < 0) {
|
||||
SDL_Log("Error when calling SDL_GetAudioDeviceFormat(default capture): %s\n", SDL_GetError());
|
||||
} else {
|
||||
SDL_Log("Default Capture Device:\n");
|
||||
SDL_Log("Sample Rate: %d\n", spec.freq);
|
||||
SDL_Log("Channels: %d\n", spec.channels);
|
||||
SDL_Log("SDL_AudioFormat: %X\n", spec.format);
|
||||
SDL_Log("Buffer Size: %d frames\n", frames);
|
||||
}
|
||||
|
||||
SDL_Quit();
|
||||
|
|
|
@ -197,7 +197,7 @@ int main(int argc, char *argv[])
|
|||
SDL_Log("Testing audio device: %s\n", devname);
|
||||
SDL_free(devname);
|
||||
|
||||
if (SDL_GetAudioDeviceFormat(devices[i], &spec) != 0) {
|
||||
if (SDL_GetAudioDeviceFormat(devices[i], &spec, NULL) != 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_GetAudioDeviceFormat() failed: %s\n", SDL_GetError());
|
||||
continue;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue