The previous code attempted to use set_buffer_size / set_period_size
discretely, favoring the parameters which generated a buffer size that was
exactly 2x the requested buffer size. This solution ultimately prioritizes
only the buffer size, which comes at a large performance cost on some machines
where this results in an excessive number of periods. In my case, for a 4096
sample buffer, this configured the device to use 37 periods with a period size
of 221 samples and a buffer size of 8192 samples. With 37 periods, the SDL
Audio thread was consuming 25% of the CPU.
This code has been refactored to use set_period_size and set_buffer_size
together. set_period_size is called first to attempt to set the period to
exactly match the requested buffer size, and set_buffer_size is called second
to further refine the parameters to attempt to use only 2 periods. The
fundamental change here is that the period size / count won't go to extreme
values if the buffer size can't be exactly matched, the buffer size should
instead just increase to the next closest multiple of the target period size
that is supported. After changing this, for a 4096 sample buffer, the device
is configured to use 3 periods with a period size of 4096 samples and a buffer
size of 12288 samples. With only 3 periods, the SDL Audio thread doesn't even
show up when profiling.
Fixes Bugzilla #4156.
This would cause playback problems in certain situations, such as on the
Raspberry Pi. The device that the wait was added for seems to not benefit from
it in modern times, and standard desktop Linux seems to do the right thing
when a USB device is unplugged now, without this patch.
Fixes Bugzilla #3599.
* alsa hotplug thread is low priority
* give a chance for other threads to catch up when audio playback is not progressing
* use nonblocking for alsa audio capture
There is a bug with SDL hanging when an audio capture USB device is removed, because poll never returns
Apparently some systems see "hw:", some see "default:" and some see
"sysdefault:" (and maybe others!). My workstation sees both "hw:" and
"sysdefault:" ...
Try to find a prefix we like and prioritize the prefixes we (think) we want
most. If everything else fails, if there's a "default" (not a prefix) device
name, list that by itself so the user gets _something_ here.
If we can't find a prefix we like _and_ there's no "default" device, report
no hardware found at all.
I think this was important for SDL 1.2 because some targets needed
special device memory for DMA buffers or locked memory buffers for use in
hardware interrupts or something, but since it just defines to SDL_malloc
and SDL_free now, I took it out for clarity's sake.
- It's now always called if device->hidden isn't NULL, even if OpenDevice()
failed halfway through. This lets implementation code not have to clean up
itself on every possible failure point; just return an error and SDL will
handle it for you.
- Implementations can assume this->hidden != NULL and not check for it.
- implementations don't have to set this->hidden = NULL when done, because
the caller is always about to free(this).
- Don't reset other fields that are in a block of memory about to be free()'d.
- Implementations all now free things like internal mix buffers last, after
closing devices and such, to guarantee they definitely aren't in use anymore
at the point of deallocation.
This is kind of nasty, because ALSA reports dozens of "devices" that aren't
really things you'd ever want, or things that should be listed this way, but
the default path still works as before, and it at least allows these devices
to be available to apps.
This does not handle hotplugging yet. You get a device list at init time
and that's it.
The internal function SDL_EGL_LoadLibrary() did not delete and remove a mostly
uninitialized data structure if loading the library first failed. A later try to
use EGL then skipped initialization and assumed it was previously successful
because the data structure now already existed. This led to at least one crash
in the internal function SDL_EGL_ChooseConfig() because a NULL pointer was
dereferenced to make a call to eglBindAPI().