The audio processing thread isn't scheduled in lock-step with the audio callback so sometimes the callback would consume the same data twice and sometimes the audio processing thread would write to the same buffer twice.
Also handle variable sizes in the audio callback so the Android audio system doesn't have to do additional buffering to match our buffer size requirements.
Saves locks and copies during audio thread iteration. We've added asserts
that can evaporate out in release mode to make sure everything stays in sync.
This fires if an opened device changes formats (which it can on Windows,
if the user changes this in the system control panel, and WASAPI can
report), or if a default device migrates to new hardware and the format
doesn't match.
This will fire for all logical devices on a physical device (and if it's
a format change and not a default device change, it'll fire for the
physical device too, but that's honestly not that useful and might change).
Fixes#8267.
("preconverted bytes" makes it sounds like we already converted them before
the call instead of "bytes that haven't yet hit the stage where we convert
them. Just dump the wording completely.)
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).