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.

Constructors

Link copied to clipboard
constructor()

Properties

Link copied to clipboard
open override val cutsSoundOnStop: Boolean

Stopping a line cuts the sound where it is, so the engine fades it first (#486).

Link copied to clipboard
open override val deviceBufferFrames: Int
Link copied to clipboard
open override val events: Flow<AudioSinkEvent>
Link copied to clipboard
open override val latencyQuality: LatencyQuality

Honestly LatencyQuality.Estimated, and it can never be better.

Link copied to clipboard

Functions

Link copied to clipboard
open override fun close()
Link copied to clipboard
open suspend override fun drain()
Link copied to clipboard
open override fun latencyNanos(): Long
Link copied to clipboard
open suspend override fun open(request: AudioFormat, render: AudioRenderCallback): AudioFormat
Link copied to clipboard
open fun setContent(content: AudioContent)
Link copied to clipboard
open suspend override fun setPaused(paused: Boolean): Boolean
Link copied to clipboard
open suspend override fun start()
Link copied to clipboard
open suspend override fun stop()