On this page:
13.1 Availability
opusfile-available?
13.2 Output format setting
opusfile-output-format?
current-opusfile-output-format
13.3 Validation
opusfile-valid?
13.4 Opening
opusfile-open
13.5 Reading
opusfile-read
13.6 Seeking
opusfile-seek
13.7 Stopping
opusfile-stop
13.8 Notes
9.3.0.2

13 opusfile-decoder🔗ℹ

Hans Dijkema <hans@dijkewijk.nl>

 (require racket-audio/opusfile-decoder)
  package: racket-audio

This module provides an Opus decoder backend based on Xiph libopusfile. It opens Ogg Opus files, reports stream information through a callback, streams decoded interleaved PCM buffers, and supports stopping and seeking.

The module is intended to be used through racket-audio/audio-decoder, but its procedures can also be used directly.

Opus decoding produces 48 kHz PCM. The original input rate stored in an Opus file, if present, is not the decoder output sample rate.

13.1 Availability🔗ℹ

procedure

(opusfile-available?)  boolean?

Returns #t if libopusfile and the native procedures used by this backend could be loaded, and #f otherwise.

The generic racket-audio/audio-decoder module prefers this decoder for Opus streams when it is available. If it is not available, Opus files may still be handled by the FFmpeg backend if that backend is available.

13.2 Output format setting🔗ℹ

procedure

(opusfile-output-format? v)  boolean?

  v : any/c
Returns #t when v is one of the supported Opus decoder output formats: 's16 or 's24.

A global output-format setting for this decoder.

Called without arguments, it returns the current output format. Called with one argument, it sets the current output format and returns the new value. The accepted values are:

  • 's16 signed 16-bit interleaved PCM. This is the default. The backend uses op_read.

  • 's24 packed signed 24-bit interleaved PCM in native byte order. The backend uses op_read_float and converts the float samples to 24-bit PCM.

The setting is global. It is read when stream format hashes are produced and when audio buffers are decoded. For normal use, set it before opening or reading an Opus file.

Example:

(current-opusfile-output-format 's24)

This binding is also re-exported by racket-audio/audio-decoder and by racket-audio/main.

13.3 Validation🔗ℹ

procedure

(opusfile-valid? audio-file)  boolean?

  audio-file : any/c
Returns #t when libopusfile is available and audio-file exists.

This predicate is deliberately small. Detailed validation is performed when the file is opened by opusfile-open. The generic decoder layer also performs extension and existence checks before opening a file.

13.4 Opening🔗ℹ

procedure

(opusfile-open audio-file    
  cb-stream-info    
  cb-audio)  (or/c struct? #f)
  audio-file : (or/c path? string?)
  cb-stream-info : procedure?
  cb-audio : procedure?
Opens audio-file with libopusfile and returns an opaque Opus decoder handle. If audio-file is a path, it is converted with path->string. If the file does not exist, the result is #f.

If libopusfile cannot be loaded, an exception is raised. If the file exists but cannot be opened by libopusfile, an exception is raised with the native Opusfile error code.

The stream-info callback is called once after the file has been opened:

(cb-stream-info info)

where info is a mutable hash containing at least:

  • 'duration duration in seconds, based on the total number of decoded PCM samples when available;

  • 'sample-rate always 48000;

  • 'channels number of decoded channels;

  • 'bits-per-sample 16 for 's16 and 24 for 's24;

  • 'bytes-per-sample 2 for 's16 and 3 for 's24;

  • 'sample-format the value of current-opusfile-output-format;

  • 'total-samples total number of decoded PCM samples, or the value reported by libopusfile.

13.5 Reading🔗ℹ

procedure

(opusfile-read handle)  any/c

  handle : struct?
Starts the decode loop for handle.

The loop repeatedly decodes audio blocks and invokes the audio callback:

(cb-audio info buffer size)

where info is the mutable stream-info hash, buffer is an interleaved PCM buffer, and size is the buffer size in bytes. Before each callback, the info hash is updated in place with:

  • 'sample the current decoded sample position;

  • 'current-time the current decoded time in seconds.

The buffer format is determined by current-opusfile-output-format. In 's16 mode the buffer contains signed 16-bit PCM. In 's24 mode the buffer contains packed signed 24-bit PCM.

The loop also checks for a pending seek request. If a seek has been requested with opusfile-seek, it is applied before the next read from libopusfile.

The loop terminates at end-of-stream or when a stop has been requested with opusfile-stop. After termination, the underlying libopusfile handle is freed.

13.6 Seeking🔗ℹ

procedure

(opusfile-seek handle percentage)  void?

  handle : struct?
  percentage : number?
Requests a seek within the stream.

The percentage argument represents a position relative to the full stream, where 0 is the start and 100 is the end. The value may be fractional and is clamped to that range.

If the total sample count is known and non-zero, the procedure computes a target decoded sample and stores it as a pending seek request. The actual native seek is performed later by opusfile-read.

13.7 Stopping🔗ℹ

procedure

(opusfile-stop handle)  void?

  handle : struct?
Requests termination of an active opusfile-read loop.

The procedure sets an internal stop flag and waits until the read loop has terminated, sleeping briefly between checks.

13.8 Notes🔗ℹ

The Opusfile backend is registered in racket-audio/audio-decoder as reader type 'opusfile for files and streams recognized as Opus.

The generic decoder callbacks therefore receive 'opusfile as audio-type and 'ao as ao-type.