Skip to content

load(_many)

Decode an audio file (or bytes) to float32 numpy, with frame-accurate offset/duration, optional resampling and downmix, all in the native extension. WAV, MP3, and FLAC take dedicated single-header decoders; OGG, MP4/AAC, and everything else go through the dynamically linked decoder libraries. load_many runs the same decode across a worker pool, one call for a whole file list.

load

specux.audio.load(path, *, sr=None, offset=0.0, duration=None, mono=False,
dtype="float32", quality="high", backend="auto",
threads=0, mmap=False, track=0, strict=True)
y, sr = specux.audio.load("song.mp3") # (channels, frames)
y, sr = specux.audio.load("song.flac", sr=16000, mono=True, duration=30.0)
y, sr = specux.audio.load(open("song.wav", "rb").read()) # bytes work too
  • sr: resample to this rate during the decode (quality picks the recipe, "quick" through "very_high").
  • offset / duration: seconds, frame-accurate (MP3 seeks through the frame table, not by bitrate estimate).
  • track: stream index for multi-track containers (stems); info reports how many there are.
  • strict=False: salvage the decodable prefix of a truncated file.
  • mmap: WAV fast path that maps the PCM instead of reading it.

load_many

The batch form: decode a list of paths in parallel (the decoders release the GIL, so this scales across cores). Every load keyword passes through and applies to every file.

import glob
paths = sorted(glob.glob("dataset/*.flac"))
ys = specux.audio.load_many(paths) # [(y, sr), ...]
ys = specux.audio.load_many(paths, sr=16000, mono=True, workers=8)
  • workers=0: one worker per core.
  • on_error="skip": put the exception in the result list at that position instead of raising, so one broken file does not lose the batch:
got = specux.audio.load_many(paths, on_error="skip")
good = [g for g in got if not isinstance(g, Exception)]

The mirror for writing is save(_many); for files too large to hold in memory, see streaming.