97 lines
4.5 KiB
Racket
97 lines
4.5 KiB
Racket
#lang scribble/manual
|
|
|
|
@(require racket/runtime-path
|
|
scribble/core
|
|
scribble/html-properties
|
|
(for-label racket/base
|
|
racket/path
|
|
"../audio-player.rkt"
|
|
"../taglib.rkt"
|
|
"../audio-sniffer.rkt"
|
|
"../audio-decoder.rkt"
|
|
"../audio-placed-player.rkt"
|
|
"../libao.rkt"
|
|
"../mp3-decoder.rkt"
|
|
"../flac-decoder.rkt"
|
|
"../ffmpeg-decoder.rkt"))
|
|
|
|
@(define-runtime-path rktplayer-logo "rktplayer.svg")
|
|
|
|
@(define title-logo-style
|
|
(style #f
|
|
(list (attributes
|
|
'((style . "float: right; margin-left: 1.5em; margin-bottom: 0.5em;"))))))
|
|
|
|
@elem[#:style title-logo-style]{@image[#:scale 0.25 rktplayer-logo]}
|
|
|
|
@title{@elem{Introduction racket-audio}}
|
|
|
|
|
|
@;;title{racket-audio}
|
|
@author[@author+email["Hans Dijkema" "hans@dijkewijk.nl"]]
|
|
|
|
@racketmodname[racket-audio] is a small audio playback toolkit for Racket. It
|
|
combines high-level asynchronous playback, optional metadata reading, file type
|
|
sniffing, decoder backends, and libao based output. Most applications should
|
|
start with the high-level player API and only use the lower-level modules when
|
|
they need to add a decoder, inspect the playback pipeline, or debug the native
|
|
FFI boundary.
|
|
|
|
@section{APIs for normal users}
|
|
|
|
For ordinary playback, use @racketmodname[racket-audio/audio-player]. It
|
|
creates an audio player, starts the worker side, and exposes procedures such as
|
|
@racket[make-audio-player], @racket[audio-play!], @racket[audio-pause!],
|
|
@racket[audio-stop!], @racket[audio-seek!], and @racket[audio-quit!]. The
|
|
player is asynchronous: commands return after they have been accepted, while
|
|
state updates and end-of-stream notifications are delivered through callbacks.
|
|
|
|
Use @racketmodname[racket-audio/taglib] when an application needs metadata such
|
|
as title, artist, album, duration-related properties, generic TagLib properties,
|
|
or embedded cover art. The module reads metadata into a Racket-side snapshot
|
|
and does not keep the native TagLib file handle open.
|
|
|
|
Use @racketmodname[racket-audio/audio-sniffer] when file type detection should
|
|
be based on file contents rather than only on extensions. The sniffer is useful
|
|
before choosing a decoder, validating input, or presenting a likely media type
|
|
to the user.
|
|
|
|
The @racketmodname[racket-audio/play-test] module is not a library API, but it
|
|
is a useful integration example. In particular, its queue mode, selected with
|
|
@racket[(set-test 'queue)], shows how an EOF callback can start the next item
|
|
in a simple playback queue.
|
|
|
|
@section{Lower-level modules for geeks}
|
|
|
|
The modules below are normally used by the player implementation rather than by
|
|
application code. They are documented because they are useful when extending,
|
|
debugging, or replacing parts of the pipeline.
|
|
|
|
@itemlist[#:style 'compact
|
|
@item{@racketmodname[racket-audio/audio-placed-player] implements the worker
|
|
side of the high-level player. It is normally run in a Racket place, so
|
|
the timing-sensitive audio feeder runs in a separate VM, but it can also
|
|
be run in a thread with async channels for easier debugging.}
|
|
@item{@racketmodname[racket-audio/audio-decoder] provides the decoder registry
|
|
and a uniform open/read/seek/stop interface over concrete decoder
|
|
backends.}
|
|
@item{@racketmodname[racket-audio/mp3-decoder],
|
|
@racketmodname[racket-audio/flac-decoder], and
|
|
@racketmodname[racket-audio/ffmpeg-decoder] are concrete decoder
|
|
frontends. The FFmpeg path is the general-purpose fallback for formats
|
|
not handled by the specialised decoders.}
|
|
@item{@racketmodname[racket-audio/libao] and
|
|
@racketmodname[racket-audio/libao-async-ffi-racket] form the output side:
|
|
they open the native audio device, queue PCM buffers, apply volume, and
|
|
feed libao asynchronously.}
|
|
@item{@racketmodname[racket-audio/ffmpeg-ffi],
|
|
@racketmodname[racket-audio/ffmpeg-definitions], and the FFmpeg C backend
|
|
documentation describe the native FFmpeg boundary, the direct FFI
|
|
definitions, version-sensitive structures, and the fixed PCM format used
|
|
by the decoder pipeline.}]
|
|
|
|
In short: applications should usually combine
|
|
@racketmodname[racket-audio/audio-player] with @racketmodname[racket-audio/taglib].
|
|
The other modules document the machinery underneath: format detection, decoder
|
|
selection, place-based playback, buffering, native output, and FFmpeg access.
|