This gives us a cheap way to wake up all PlaybackStream implementations
when they are sleeping due to an underrun. The new function is meant to
be very cheap so that it can be unconditionally called when new data is
ready to be written.
This will allow the audio sink to rely on streams to track the time in
written audio frames instead of writing silence when data isn't ready.
The WASAPI implementation was actually polling for new data every 10ms
after hitting an underrun, so now it drains the buffers and stops when
entering the underrun-paused state.
This commit splits out synchronization primitives from LibThreading into
LibSync. This is because LibThreading depends on LibCore, while LibCore
needs the synchronization primitives from LibThreading. This worked
while they were header only, but when I tried to add an implementation
file it ran into the circular dependency. To abstract away the pthread
implementation using cpp files is necessary so the synchronization
primitives were moved to a separate library.
This allows us to avoid returning a PlaybackStream in cases where the
async initialization fails.
This is a step towards more graceful fallbacks when audio fails in
AudioMixingSink.
Implement PlaybackStream using WASAPI. The design is similar to
PlaybackStreamAudioUnit in that it uses a task queue. A high priority
thread is used to render the stream. All the stream controls save for
the exit being requested which happens on destruction of the stream are
managed by the render thread.
Due to the design of the windows audio mixer the audio we receive must
be resampled to match the sample rate of the mixer. We use a float based
interleaved PCM stream which matches both our existing code and the
audio mixer which internally usues floats.
Having to use a mutex around a queue for the task queue is suboptimal,
in a future PR a MPSC queue could be added to AK and used instead.