#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{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.