You can see it in action in testaudio by mousing over a logical device; it
will show a visualizer for the current PCM (whatever is currently being
recorded on a capture device, or whatever is being mixed for output on
playback devices).
Fixes#8122.
This is adds complexity and fragility for small optimization wins.
The biggest win is the extremely common case of a single stream providing
the only output, so we'll check for that and skip silencing/mixing/converting.
Otherwise, just use a single mixer path.
This only does this work if actually mixing; if the physical device only
has a single stream bound to it, it'll just write the data to the hardware
without the extra drama.
Fixes#8123.
Currently it's SILENCE (just zero out the mix buffer), COPYONE (one stream
writes directly into the hardware's buffer), or MIX (everything gets mixed
together before sending to the hardware).
Devices that aren't doing anything result in SILENCE. Devices playing
one thing result in COPYONE.
This lets the two most common states take what are likely significantly
faster approaches.
There will likely be some other strategies later (like when we offer a
postmix callback, etc).
This is meant to offer a simplified API for people that are either migrating
directly from SDL2 with minimal effort or just want to make noise without
any of the fancy new API features.
Users of this API can just deal with a single SDL_AudioStream as their only
object/handle into the audio subsystem.
They are still allowed to open multiple devices (or open the same device
multiple times), but cannot change stream bindings on logical devices opened
through this function.
Destroying the single audio stream will also close the logical device behind
the scenes.
This involved moving an `#ifdef` out of SDL_audio.c for thread priority,
so the default ThreadInit now does the usual stuff for non-Android platforms,
the Android platforms provide an implementatin of ThreadInit with their
side of the `#ifdef` and other platforms that implement ThreadInit
incorporated the appropriate code...which is why WASAPI is touched in here.
The Android bits compile, but have not been tested, and there was some
reworkings in the Java bits, so this might need some further fixes still.
Every single case of this didn't want the device locked, so just looking
it up without having to immediately unlock it afterwards is better here.
Often these devices are passed on to other functions that want to lock them
themselves anyhow (disconnects, default changes, etc).
Before it would just block in read operations, but separating this out
matches what output devices already do, and also lets us separate out the
unlocked waiting part from the fast part that holds the device lock.
This means "I don't care what format I get at all" and will just use
the device's current (and/or default) format.
This can be useful, since audio streams cover the differences anyhow.
Zombie devices just sit there doing nothing until a new default device
is chosen, and then they migrate all their logical devices before being
destroyed.
This lets the system deal with the likely outcome of a USB headset being
the default audio device, and when its cable is yanked out, the backend
will likely announce this _before_ it chooses a new default (or, perhaps,
the only device in the system got yanked out and there _isn't_ a new
default to be had until the user plugs the cable back in).
This lets the audio device hold on without disturbing the app until it can
seamlessly migrate audio, and it also means the backend does not have to
be careful in how it announces device events, since SDL will manage the
time between a device loss and its replacement.
Note that this _only_ applies to things opened as the default device
(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, etc). If those USB headphones are the
default, and one SDL_OpenAudioDevice() call asked for them specifically and
the other just said "give me the system default," the explicitly requested
open will get a device-lost notification immediately. The other open will
live on as a zombie until it can migrate to the new default.
This drops the complexity of the PulseAudio hotplug thread dramatically,
back to what it was previously, since it no longer needs to fight against
Pulse's asychronous nature, but just report device disconnects and new
default choices as they arrive.
loopwave has been updated to not check for device removals anymore; since
it opens the default device, this is now managed for it; it no longer
needs to close and reopen a device, and as far as it knows, the device
is never lost in the first place.