DesktopAudioSink
The desktop JVM audio output: one javax.sound.sampled.SourceDataLine behind the engine's pull contract.
SourceDataLine is a PUSH device while the engine exposes a PULL callback that owns the audio clock anchor. The adaptation is the one wrapper the AudioSink KDoc names for push platforms: a dedicated writer thread turns "the line has room" into a pull. Each loop iteration computes the deadline of the LAST frame of the block, invokes the engine's AudioRenderCallback into a preallocated buffer, silences any tail a short return leaves (nothing above the sink zeroes it, per the callback contract), packs the floats to the wire encoding, and loops write until the block is fully submitted or a lifecycle signal lands. This is AudioTrackSink's proven writer machine, because the audit rows it closed apply here word for word.
The sink accepts mono or stereo and never converts: mixing and resampling stay in the engine. The one thing it does do is the packing the SPI explicitly allows, F32 to 16-bit signed little-endian, because the JDK's own mixers refuse float lines (see WIRE_BYTES_PER_SAMPLE).
A sink bound to one output mixer checks about once a second that the mixer is still listed, from open to close. When it is gone, the sink sends AudioSinkEvent.Failed with PlaybackError.AudioDeviceUnavailable, because a line on a vanished mixer may block in write and report nothing. A sink on the system default checks nothing.
The internal constructor takes the driver factory and the clock so the host suite drives every lifecycle and arithmetic arm with a fake; the public constructor hard-wires DesktopMonotonicClock, so production cannot pair the deadlines with another time base.
Properties
Stopping a line cuts the sound where it is, so the engine fades it first (#486).
Honestly LatencyQuality.Estimated, and it can never be better.