libao documentation

This commit is contained in:
2026-04-21 10:38:07 +02:00
parent 57fe9ab48a
commit cd11bb77f9
2 changed files with 213 additions and 1 deletions

View File

@@ -65,8 +65,9 @@
(define (ao-valid-rate? rate) (define (ao-valid-rate? rate)
(and (integer? rate) (and (integer? rate)
(> rate 0)
(not (eq? (memq rate '(8000 11025 16000 22050 44100 (not (eq? (memq rate '(8000 11025 16000 22050 44100
48000 88200 96000 1764000 48000 88200 96000 176400
192000 352800 384000)) #f)))) 192000 352800 384000)) #f))))
(define (ao-valid-channels? c) (define (ao-valid-channels? c)

211
scrbl/libao.scrbl Normal file
View File

@@ -0,0 +1,211 @@
#lang scribble/manual
@(require racket/base
(for-label racket/base
"../libao.rkt"))
@title{libao}
@author[@author+email["Hans Dijkema" "hans@dijkewijk.nl"]]
@defmodule["libao.rkt"]
This module provides a small high-level interface to an asynchronous
audio output backend. It opens a live output device, queues audio
buffers for playback, reports playback position, supports pause and
buffer clearing, and exposes a small set of validation predicates.
The central value is an @racket[ao-handle], created by
@racket[ao-open-live]. An @racket[ao-handle] stores the playback
configuration together with a native asynchronous player handle.
@section{Audio handles}
@defproc[(ao-handle? [v any/c]) boolean?]{
Returns @racket[#t] if @racket[v] is an @racket[ao-handle] value, and
@racket[#f] otherwise.
}
@defproc[(ao-valid? [handle ao-handle?]) boolean?]{
Returns @racket[#t] if @racket[handle] still has a native asynchronous
player, and @racket[#f] otherwise.
A handle becomes invalid after @racket[ao-close], or when
@racket[ao-open-live] failed to create the native player.
}
@section{Validation predicates}
@defproc[(ao-valid-bits? [bits any/c]) boolean?]{
Returns @racket[#t] if @racket[bits] is one of @racket[8],
@racket[16], @racket[24], or @racket[32], and @racket[#f] otherwise.
}
@defproc[(ao-valid-rate? [rate any/c]) boolean?]{
Returns @racket[#t] if @racket[rate] is one of the sample rates
accepted by this module, and @racket[#f] otherwise.
The accepted rates are:
@itemlist[#:style 'compact
@item{@racket[8000], @racket[11025], @racket[16000], @racket[22050],}
@item{@racket[44100], @racket[48000], @racket[88200], @racket[96000],}
@item{@racket[176400], @racket[192000], @racket[352800], and}
@item{@racket[384000].}]
}
@defproc[(ao-valid-channels? [channels any/c]) boolean?]{
Returns @racket[#t] if @racket[channels] is an integer greater than or
equal to @racket[1], and @racket[#f] otherwise.
}
@defproc[(ao-valid-format? [format any/c]) boolean?]{
Returns @racket[#t] if @racket[format] is one of
@racket['little-endian], @racket['big-endian], or
@racket['native-endian], and @racket[#f] otherwise.
}
@defproc[(ao-supported-music-format? [format any/c]) boolean?]{
Returns @racket[#t] if @racket[format] is one of @racket['flac],
@racket['mp3], or @racket['ao], and @racket[#f] otherwise.
This value is used by @racket[ao-play] to describe the format of the
buffer being queued.
}
@section{Opening and closing}
@defproc[(ao-open-live [bits ao-valid-bits?]
[rate ao-valid-rate?]
[channels ao-valid-channels?]
[byte-format ao-valid-format?])
ao-handle?]{
Creates an audio output handle for live playback.
The handle stores the given sample size, sample rate, channel count,
and byte format. It then tries to create a native asynchronous player.
If the native player is created successfully, the returned handle is
valid. If player creation fails, the function still returns an
@racket[ao-handle], but that handle is marked closed and is not valid
for playback.
A finalizer is registered for the handle and calls @racket[ao-close]
when the handle is reclaimed.
}
@defproc[(ao-close [handle ao-handle?]) void?]{
Stops playback for @racket[handle] and releases the native player
reference stored in the handle.
If the handle already has no native player, this procedure has no
effect.
}
@section{Playback}
@defproc[(ao-play [handle ao-handle?]
[music-id integer?]
[at-time-in-s number?]
[music-duration-s number?]
[buffer any/c]
[buf-len integer?]
[buf-type ao-supported-music-format?])
void?]{
Queues audio data for asynchronous playback.
The @racket[music-id] argument identifies the music stream associated
with the buffer. The arguments @racket[at-time-in-s] and
@racket[music-duration-s] describe the position and duration, in
seconds, associated with the buffer. The arguments @racket[buffer] and
@racket[buf-len] provide the audio data and its length. The
@racket[buf-type] argument specifies the buffer format.
The buffer description passed to the native layer is completed with the
sample size, sample rate, channel count, and byte format stored in
@racket[handle].
If @racket[handle] is not valid, this procedure raises an exception.
}
@defproc[(ao-pause [handle ao-handle?]
[pause boolean?])
void?]{
Pauses or resumes asynchronous playback for @racket[handle].
A true value pauses playback. @racket[#f] resumes playback.
}
@defproc[(ao-clear-async [handle ao-handle?]) void?]{
Clears buffered asynchronous playback data for @racket[handle].
}
@section{Playback state}
@defproc[(ao-at-second [handle ao-handle?]) number?]{
Returns the current playback position, in seconds, as reported by the
native asynchronous player.
}
@defproc[(ao-at-music-id [handle ao-handle?]) integer?]{
Returns the music identifier currently reported by the native
asynchronous player.
}
@defproc[(ao-music-duration [handle ao-handle?]) number?]{
Returns the duration of the current music stream, in seconds, as
reported by the native asynchronous player.
}
@defproc[(ao-bufsize-async [handle ao-handle?]) integer?]{
Returns the current buffered size in bytes for the asynchronous player.
}
@section{Volume control}
@defproc[(ao-set-volume! [handle ao-handle?]
[percentage number?])
void?]{
Sets the playback volume for @racket[handle].
If @racket[percentage] is an exact integer, it is converted to an
inexact number before it is passed to the native layer.
}
@defproc[(ao-volume [handle ao-handle?]) number?]{
Returns the current playback volume as reported by the native
asynchronous player.
}
@section{Notes}
This module is a higher-level wrapper around the asynchronous FFI layer.
It stores the playback configuration in the handle, and reuses that
configuration for each call to @racket[ao-play].
The module does not expose the handle fields directly. The public API
is intentionally small: create a handle, queue buffers, inspect
position and buffer state, pause or clear playback, adjust volume, and
close the handle.
A typical usage pattern is to open one live handle for a given stream
format, queue decoded buffers with @racket[ao-play], and query the
playback position with @racket[ao-at-second] while playback proceeds
asynchronously.