Now it offers the total requested bytes in addition to the amount
immediately needed (and immediately needed might be zero if the stream
already has enough queued to satisfy the request.
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.
Since the top-level table is getting undefined, all the things in it will
be unreachable and eligible for garbage collection without explicitly
nulling them out.
Now, if the AudioContext starts in a "suspended" state, because the browser
blocked it from playing by default, we we run the audio "thread" in a timer
and throw away the generated audio. Once the AudioContext is allowed to
resume, we clear this timer.
The end result is that the app will continue to drain its audio queue
instead of consuming more memory over time (and, if it relies on an audio
callback to make progress, continue to run!), with the effect that the
page is merely silent but otherwise functioning as intended.
Once the user interacts with the page and the browser permits the the
AudioContext to run for real, audio should still be in sync, instead of
just starting to play audio that might now be at least several seconds behind.