Merge branch 'main' of https://git.dijkewijk.nl/hans/racket-audio
This commit is contained in:
@@ -36,11 +36,54 @@ all other procedures in this module.
|
||||
The @racket[cb-state] callback is called as:
|
||||
|
||||
@racketblock[
|
||||
(cb-state player state-hash)]
|
||||
(cb-state player current-player-state state-hash)]
|
||||
|
||||
where @racket[player] is the player handle and @racket[state-hash] is the most
|
||||
recent state snapshot received from the worker side. The callback is called
|
||||
from the event thread created by @racket[make-audio-player].
|
||||
where @racket[player] is the player handle,
|
||||
@racket[current-player-state] is the logical player state reported by the
|
||||
worker, and @racket[state-hash] is the most recent state snapshot received from
|
||||
the worker side. The callback is called from the event thread created by
|
||||
@racket[make-audio-player].
|
||||
|
||||
The worker-side player state is one of the following symbols:
|
||||
|
||||
@itemlist[
|
||||
#:style 'compact
|
||||
|
||||
@item{@racket['stopped] -- no stream is currently playing. This is the
|
||||
initial state of the placed player. The player also enters this state after
|
||||
@racket[audio-stop!] or after the decoder has reached the end of the stream
|
||||
and the libao output queue has drained.}
|
||||
|
||||
@item{@racket['playing] -- a stream is active. The decoder may still be
|
||||
reading from the input file, or the decoder may already have finished while
|
||||
libao is still playing queued PCM samples.}
|
||||
|
||||
@item{@racket['paused] -- playback is paused. The current stream is retained
|
||||
and the libao output side is paused. Resuming playback moves the player back
|
||||
to @racket['playing].}
|
||||
|
||||
@item{@racket['quit] -- the placed player has been asked to terminate. This
|
||||
is the terminal state of the worker.}
|
||||
]
|
||||
|
||||
The wrapper around the placed player may also report these states through
|
||||
@racket[audio-state]:
|
||||
|
||||
@itemlist[
|
||||
#:style 'compact
|
||||
|
||||
@item{@racket['initialized] -- the audio handle has been created, but no
|
||||
worker-side state snapshot has been received yet.}
|
||||
|
||||
@item{@racket['invalid] -- the audio handle is no longer valid. This happens
|
||||
after @racket[audio-quit!] or when the underlying place or thread has stopped.}
|
||||
]
|
||||
|
||||
The @racket[state-hash] contains the detailed playback state reported by the
|
||||
worker. It includes values such as the current playback position, stream
|
||||
duration, buffer status, music id, and libao handle validity. Code that only
|
||||
needs the logical playback state should use @racket[current-player-state]
|
||||
instead of extracting it from the hash.
|
||||
|
||||
The @racket[cb-eof-stream] callback is called as:
|
||||
|
||||
@@ -52,6 +95,8 @@ that the decoder has finished queueing the stream. The audio device may still
|
||||
have buffered samples to play, and the logical player state may move to
|
||||
@racket['stopped] slightly later when the output queue has drained.
|
||||
|
||||
End-of-stream is not represented as a separate player state.
|
||||
|
||||
When @racket[use-place] is true, @racket[make-audio-player] starts
|
||||
@racket[placed-player] with @racket[dynamic-place] and communicates with it
|
||||
through place channels. When @racket[use-place] is false, the same command loop
|
||||
@@ -65,6 +110,7 @@ other active threads in the main VM. Those delays can otherwise be heard as
|
||||
clicks, gaps, or stuttering playback. Thread mode is useful for debugging the
|
||||
protocol and callbacks, but it is not the preferred mode for robust playback.}
|
||||
|
||||
|
||||
@defproc[(audio-play? [v any/c]) boolean?]{
|
||||
Returns @racket[#t] when @racket[v] is a currently valid audio player handle.
|
||||
|
||||
@@ -157,6 +203,40 @@ is lowered to @racket[10]. A @racket[max] below @racket[min] is changed to
|
||||
@racket[30]. The worker side applies its own safe ordering and clamping before
|
||||
using the values. In normal use the return value is @racket['ok].}
|
||||
|
||||
@deftogether[
|
||||
(@defproc[(audio-ao-buf-ms! [handle audio-play?]
|
||||
[ms integer?])
|
||||
(or/c integer? boolean?)]
|
||||
@defproc[(audio-ao-buf-ms [handle audio-play?])
|
||||
(or/c integer? boolean?)])
|
||||
]{
|
||||
|
||||
Sets or queries the libao output buffer size, expressed in milliseconds.
|
||||
|
||||
The @racket[audio-ao-buf-ms!] procedure forwards @racket[ms] to the audio
|
||||
player backend by sending the @racket['ao-buf-ms] RPC command. This hooks
|
||||
into the libao-side buffer configuration and can be used to tune the amount of
|
||||
audio data that the output layer keeps ahead of playback.
|
||||
|
||||
The @racket[audio-ao-buf-ms] procedure queries the currently configured value
|
||||
by sending the same RPC command without a new value.
|
||||
|
||||
The returned value is the value reported by the backend. Normally this is an
|
||||
integer number of milliseconds. A boolean result indicates that the value could
|
||||
not be set or queried, or that the backend reported a non-numeric status.
|
||||
|
||||
Larger buffer values can make playback more robust against short scheduling
|
||||
delays, but also increase latency. Smaller values reduce latency, but may make
|
||||
drop-outs more likely when the decoder or GUI thread is temporarily delayed.
|
||||
|
||||
The value is clamped between 50 and 1000ms.
|
||||
|
||||
@racketblock[
|
||||
(audio-ao-buf-ms! player 500)
|
||||
(audio-ao-buf-ms player)
|
||||
]
|
||||
}
|
||||
|
||||
@section{State snapshots}
|
||||
|
||||
The player keeps a local cache of the most recent state snapshot received from
|
||||
|
||||
Reference in New Issue
Block a user